mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-12-01 19:49:11 +08:00
use sokol to get time
This commit is contained in:
parent
a57f360f62
commit
6629e6337a
8
3rd/sokol/.editorconfig
Normal file
8
3rd/sokol/.editorconfig
Normal file
@ -0,0 +1,8 @@
|
||||
root=true
|
||||
[**]
|
||||
indent_style=space
|
||||
indent_size=4
|
||||
trim_trailing_whitespace=true
|
||||
insert_final_newline=true
|
||||
|
||||
|
22
3rd/sokol/LICENSE
Normal file
22
3rd/sokol/LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
1062
3rd/sokol/README.md
Normal file
1062
3rd/sokol/README.md
Normal file
File diff suppressed because it is too large
Load Diff
2
3rd/sokol/fips.yml
Normal file
2
3rd/sokol/fips.yml
Normal file
@ -0,0 +1,2 @@
|
||||
exports:
|
||||
header-dirs: [ ".", "util" ]
|
7232
3rd/sokol/sokol_app.h
Normal file
7232
3rd/sokol/sokol_app.h
Normal file
File diff suppressed because it is too large
Load Diff
768
3rd/sokol/sokol_args.h
Normal file
768
3rd/sokol/sokol_args.h
Normal file
@ -0,0 +1,768 @@
|
||||
#ifndef SOKOL_ARGS_INCLUDED
|
||||
/*
|
||||
sokol_args.h -- cross-platform key/value arg-parsing for web and native
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
Optionally provide the following defines with your own implementations:
|
||||
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_LOG(msg) - your own logging functions (default: puts(msg))
|
||||
SOKOL_CALLOC(n,s) - your own calloc() implementation (default: calloc(n,s))
|
||||
SOKOL_FREE(p) - your own free() implementation (default: free(p))
|
||||
SOKOL_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
If sokol_args.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
sokol_args.h provides a simple unified argument parsing API for WebAssembly and
|
||||
native apps.
|
||||
|
||||
When running as WebAssembly app, arguments are taken from the page URL:
|
||||
|
||||
https://floooh.github.io/tiny8bit/kc85.html?type=kc85_3&mod=m022&snapshot=kc85/jungle.kcc
|
||||
|
||||
The same arguments provided to a command line app:
|
||||
|
||||
kc85 type=kc85_3 mod=m022 snapshot=kc85/jungle.kcc
|
||||
|
||||
ARGUMENT FORMATTING
|
||||
===================
|
||||
On the web platform, arguments must be formatted as a valid URL query string
|
||||
with 'percent encoding' used for special characters.
|
||||
|
||||
Strings are expected to be UTF-8 encoded (although sokol_args.h doesn't
|
||||
contain any special UTF-8 handling). See below on how to obtain
|
||||
UTF-8 encoded argc/argv values on Windows when using WinMain() as
|
||||
entry point.
|
||||
|
||||
On native platforms the following rules must be followed:
|
||||
|
||||
Arguments have the general form
|
||||
|
||||
key=value
|
||||
|
||||
Key/value pairs are separated by 'whitespace', valid whitespace
|
||||
characters are space and tab.
|
||||
|
||||
Whitespace characters in front and after the separating '=' character
|
||||
are ignored:
|
||||
|
||||
key = value
|
||||
|
||||
...is the same as
|
||||
|
||||
key=value
|
||||
|
||||
The 'key' string must be a simple string without escape sequences or whitespace.
|
||||
|
||||
Currently 'single keys' without values are not allowed, but may be
|
||||
in the future.
|
||||
|
||||
The 'value' string can be quoted, and quoted value strings can contain
|
||||
whitespace:
|
||||
|
||||
key = 'single-quoted value'
|
||||
key = "double-quoted value"
|
||||
|
||||
Single-quoted value strings can contain double quotes, and vice-versa:
|
||||
|
||||
key = 'single-quoted value "can contain double-quotes"'
|
||||
key = "double-quoted value 'can contain single-quotes'"
|
||||
|
||||
Note that correct quoting can be tricky on some shells, since command
|
||||
shells may remove quotes, unless they're escaped.
|
||||
|
||||
Value strings can contain a small selection of escape sequences:
|
||||
|
||||
\n - newline
|
||||
\r - carriage return
|
||||
\t - tab
|
||||
\\ - escaped backslash
|
||||
|
||||
(more escape codes may be added in the future).
|
||||
|
||||
CODE EXAMPLE
|
||||
============
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// initialize sokol_args with default parameters
|
||||
sargs_setup(&(sargs_desc){
|
||||
.argc = argc,
|
||||
.argv = argv
|
||||
});
|
||||
|
||||
// check if a key exists...
|
||||
if (sargs_exists("bla")) {
|
||||
...
|
||||
}
|
||||
|
||||
// get value string for key, if not found, return empty string ""
|
||||
const char* val0 = sargs_value("bla");
|
||||
|
||||
// get value string for key, or default string if key not found
|
||||
const char* val1 = sargs_value_def("bla", "default_value");
|
||||
|
||||
// check if a key matches expected value
|
||||
if (sargs_equals("type", "kc85_4")) {
|
||||
...
|
||||
}
|
||||
|
||||
// check if a key's value is "true", "yes" or "on"
|
||||
if (sargs_boolean("joystick_enabled")) {
|
||||
...
|
||||
}
|
||||
|
||||
// iterate over keys and values
|
||||
for (int i = 0; i < sargs_num_args(); i++) {
|
||||
printf("key: %s, value: %s\n", sargs_key_at(i), sargs_value_at(i));
|
||||
}
|
||||
|
||||
// lookup argument index by key string, will return -1 if key
|
||||
// is not found, sargs_key_at() and sargs_value_at() will return
|
||||
// an empty string for invalid indices
|
||||
int index = sargs_find("bla");
|
||||
printf("key: %s, value: %s\n", sargs_key_at(index), sargs_value_at(index));
|
||||
|
||||
// shutdown sokol-args
|
||||
sargs_shutdown();
|
||||
}
|
||||
|
||||
WINMAIN AND ARGC / ARGV
|
||||
=======================
|
||||
On Windows with WinMain() based apps, use the __argc and __argv global
|
||||
variables provided by Windows. These are compatible with main(argc, argv)
|
||||
and have already been converted to UTF-8 by Windows:
|
||||
|
||||
int WINAPI WinMain(...) {
|
||||
sargs_setup(&(sargs_desc){
|
||||
.argc = __argc,
|
||||
.argv = __argv
|
||||
});
|
||||
}
|
||||
|
||||
(this is also what sokol_app.h uses btw)
|
||||
|
||||
API DOCUMENTATION
|
||||
=================
|
||||
void sargs_setup(const sargs_desc* desc)
|
||||
Initialize sokol_args, desc contains the following configuration
|
||||
parameters:
|
||||
int argc - the main function's argc parameter
|
||||
char** argv - the main function's argv parameter
|
||||
int max_args - max number of key/value pairs, default is 16
|
||||
int buf_size - size of the internal string buffer, default is 16384
|
||||
|
||||
Note that on the web, argc and argv will be ignored and the arguments
|
||||
will be taken from the page URL instead.
|
||||
|
||||
sargs_setup() will allocate 2 memory chunks: one for keeping track
|
||||
of the key/value args of size 'max_args*8', and a string buffer
|
||||
of size 'buf_size'.
|
||||
|
||||
void sargs_shutdown(void)
|
||||
Shutdown sokol-args and free any allocated memory.
|
||||
|
||||
bool sargs_isvalid(void)
|
||||
Return true between sargs_setup() and sargs_shutdown()
|
||||
|
||||
bool sargs_exists(const char* key)
|
||||
Test if a key arg exists.
|
||||
|
||||
const char* sargs_value(const char* key)
|
||||
Return value associated with key. Returns an empty
|
||||
string ("") if the key doesn't exist.
|
||||
|
||||
const char* sargs_value_def(const char* key, const char* default)
|
||||
Return value associated with key, or the provided default
|
||||
value if the value doesn't exist.
|
||||
|
||||
bool sargs_equals(const char* key, const char* val);
|
||||
Return true if the value associated with key matches
|
||||
the 'val' argument.
|
||||
|
||||
bool sargs_boolean(const char* key)
|
||||
Return true if the value string of 'key' is one
|
||||
of 'true', 'yes', 'on'.
|
||||
|
||||
int sargs_find(const char* key)
|
||||
Find argument by key name and return its index, or -1 if not found.
|
||||
|
||||
int sargs_num_args(void)
|
||||
Return number of key/value pairs.
|
||||
|
||||
const char* sargs_key_at(int index)
|
||||
Return the key name of argument at index. Returns empty string if
|
||||
is index is outside range.
|
||||
|
||||
const char* sargs_value_at(int index)
|
||||
Return the value of argument at index. Returns empty string
|
||||
if index is outside range.
|
||||
|
||||
TODO
|
||||
====
|
||||
- parsing errors?
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_ARGS_INCLUDED (1)
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef SOKOL_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_IMPL)
|
||||
#define SOKOL_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct sargs_desc {
|
||||
int argc;
|
||||
char** argv;
|
||||
int max_args;
|
||||
int buf_size;
|
||||
} sargs_desc;
|
||||
|
||||
/* setup sokol-args */
|
||||
SOKOL_API_DECL void sargs_setup(const sargs_desc* desc);
|
||||
/* shutdown sokol-args */
|
||||
SOKOL_API_DECL void sargs_shutdown(void);
|
||||
/* true between sargs_setup() and sargs_shutdown() */
|
||||
SOKOL_API_DECL bool sargs_isvalid(void);
|
||||
/* test if an argument exists by key name */
|
||||
SOKOL_API_DECL bool sargs_exists(const char* key);
|
||||
/* get value by key name, return empty string if key doesn't exist */
|
||||
SOKOL_API_DECL const char* sargs_value(const char* key);
|
||||
/* get value by key name, return provided default if key doesn't exist */
|
||||
SOKOL_API_DECL const char* sargs_value_def(const char* key, const char* def);
|
||||
/* return true if val arg matches the value associated with key */
|
||||
SOKOL_API_DECL bool sargs_equals(const char* key, const char* val);
|
||||
/* return true if key's value is "true", "yes" or "on" */
|
||||
SOKOL_API_DECL bool sargs_boolean(const char* key);
|
||||
/* get index of arg by key name, return -1 if not exists */
|
||||
SOKOL_API_DECL int sargs_find(const char* key);
|
||||
/* get number of parsed arguments */
|
||||
SOKOL_API_DECL int sargs_num_args(void);
|
||||
/* get key name of argument at index, or empty string */
|
||||
SOKOL_API_DECL const char* sargs_key_at(int index);
|
||||
/* get value string of argument at index, or empty string */
|
||||
SOKOL_API_DECL const char* sargs_value_at(int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif // SOKOL_ARGS_INCLUDED
|
||||
|
||||
/*--- IMPLEMENTATION ---------------------------------------------------------*/
|
||||
#ifdef SOKOL_IMPL
|
||||
#define SOKOL_ARGS_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset, strcmp */
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define SOKOL_DEBUG (1)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
#if !defined(SOKOL_CALLOC) && !defined(SOKOL_FREE)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if !defined(SOKOL_CALLOC)
|
||||
#define SOKOL_CALLOC(n,s) calloc(n,s)
|
||||
#endif
|
||||
#if !defined(SOKOL_FREE)
|
||||
#define SOKOL_FREE(p) free(p)
|
||||
#endif
|
||||
#ifndef SOKOL_LOG
|
||||
#ifdef SOKOL_DEBUG
|
||||
#include <stdio.h>
|
||||
#define SOKOL_LOG(s) { SOKOL_ASSERT(s); puts(s); }
|
||||
#else
|
||||
#define SOKOL_LOG(s)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _SOKOL_PRIVATE
|
||||
#if defined(__GNUC__)
|
||||
#define _SOKOL_PRIVATE __attribute__((unused)) static
|
||||
#else
|
||||
#define _SOKOL_PRIVATE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _sargs_def(val, def) (((val) == 0) ? (def) : (val))
|
||||
|
||||
#define _SARGS_MAX_ARGS_DEF (16)
|
||||
#define _SARGS_BUF_SIZE_DEF (16*1024)
|
||||
|
||||
/* parser state (no parser needed on emscripten) */
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
#define _SARGS_EXPECT_KEY (1<<0)
|
||||
#define _SARGS_EXPECT_SEP (1<<1)
|
||||
#define _SARGS_EXPECT_VAL (1<<2)
|
||||
#define _SARGS_PARSING_KEY (1<<3)
|
||||
#define _SARGS_PARSING_VAL (1<<4)
|
||||
#define _SARGS_ERROR (1<<5)
|
||||
#endif
|
||||
|
||||
/* a key/value pair struct */
|
||||
typedef struct {
|
||||
int key; /* index to start of key string in buf */
|
||||
int val; /* index to start of value string in buf */
|
||||
} _sargs_kvp_t;
|
||||
|
||||
/* sokol-args state */
|
||||
typedef struct {
|
||||
int max_args; /* number of key/value pairs in args array */
|
||||
int num_args; /* number of valid items in args array */
|
||||
_sargs_kvp_t* args; /* key/value pair array */
|
||||
int buf_size; /* size of buffer in bytes */
|
||||
int buf_pos; /* current buffer position */
|
||||
char* buf; /* character buffer, first char is reserved and zero for 'empty string' */
|
||||
bool valid;
|
||||
|
||||
/* arg parsing isn't needed on emscripten */
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
uint32_t parse_state;
|
||||
char quote; /* current quote char, 0 if not in a quote */
|
||||
bool in_escape; /* currently in an escape sequence */
|
||||
#endif
|
||||
} _sargs_state_t;
|
||||
static _sargs_state_t _sargs;
|
||||
|
||||
/*== PRIVATE IMPLEMENTATION FUNCTIONS ========================================*/
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_putc(char c) {
|
||||
if ((_sargs.buf_pos+2) < _sargs.buf_size) {
|
||||
_sargs.buf[_sargs.buf_pos++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE const char* _sargs_str(int index) {
|
||||
SOKOL_ASSERT((index >= 0) && (index < _sargs.buf_size));
|
||||
return &_sargs.buf[index];
|
||||
}
|
||||
|
||||
/*-- argument parser functions (not required on emscripten) ------------------*/
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
_SOKOL_PRIVATE void _sargs_expect_key(void) {
|
||||
_sargs.parse_state = _SARGS_EXPECT_KEY;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_key_expected(void) {
|
||||
return 0 != (_sargs.parse_state & _SARGS_EXPECT_KEY);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_expect_val(void) {
|
||||
_sargs.parse_state = _SARGS_EXPECT_VAL;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_val_expected(void) {
|
||||
return 0 != (_sargs.parse_state & _SARGS_EXPECT_VAL);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_expect_sep(void) {
|
||||
_sargs.parse_state = _SARGS_EXPECT_SEP;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_sep_expected(void) {
|
||||
return 0 != (_sargs.parse_state & _SARGS_EXPECT_SEP);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_any_expected(void) {
|
||||
return 0 != (_sargs.parse_state & (_SARGS_EXPECT_KEY | _SARGS_EXPECT_VAL | _SARGS_EXPECT_SEP));
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_is_separator(char c) {
|
||||
return c == '=';
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_is_quote(char c) {
|
||||
if (0 == _sargs.quote) {
|
||||
return (c == '\'') || (c == '"');
|
||||
}
|
||||
else {
|
||||
return c == _sargs.quote;
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_begin_quote(char c) {
|
||||
_sargs.quote = c;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_end_quote(void) {
|
||||
_sargs.quote = 0;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_in_quotes(void) {
|
||||
return 0 != _sargs.quote;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_is_whitespace(char c) {
|
||||
return !_sargs_in_quotes() && ((c == ' ') || (c == '\t'));
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_start_key(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
_sargs.parse_state = _SARGS_PARSING_KEY;
|
||||
_sargs.args[_sargs.num_args].key = _sargs.buf_pos;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_end_key(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
_sargs_putc(0);
|
||||
_sargs.parse_state = 0;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_parsing_key(void) {
|
||||
return 0 != (_sargs.parse_state & _SARGS_PARSING_KEY);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_start_val(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
_sargs.parse_state = _SARGS_PARSING_VAL;
|
||||
_sargs.args[_sargs.num_args].val = _sargs.buf_pos;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_end_val(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
_sargs_putc(0);
|
||||
_sargs.num_args++;
|
||||
_sargs.parse_state = 0;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_is_escape(char c) {
|
||||
return '\\' == c;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_start_escape(void) {
|
||||
_sargs.in_escape = true;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_in_escape(void) {
|
||||
return _sargs.in_escape;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE char _sargs_escape(char c) {
|
||||
switch (c) {
|
||||
case 'n': return '\n';
|
||||
case 't': return '\t';
|
||||
case 'r': return '\r';
|
||||
case '\\': return '\\';
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_end_escape(void) {
|
||||
_sargs.in_escape = false;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_parsing_val(void) {
|
||||
return 0 != (_sargs.parse_state & _SARGS_PARSING_VAL);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) {
|
||||
char c;
|
||||
while (0 != (c = *src++)) {
|
||||
if (_sargs_in_escape()) {
|
||||
c = _sargs_escape(c);
|
||||
_sargs_end_escape();
|
||||
}
|
||||
else if (_sargs_is_escape(c)) {
|
||||
_sargs_start_escape();
|
||||
continue;
|
||||
}
|
||||
if (_sargs_any_expected()) {
|
||||
if (!_sargs_is_whitespace(c)) {
|
||||
/* start of key, value or separator */
|
||||
if (_sargs_key_expected()) {
|
||||
/* start of new key */
|
||||
_sargs_start_key();
|
||||
}
|
||||
else if (_sargs_val_expected()) {
|
||||
/* start of value */
|
||||
if (_sargs_is_quote(c)) {
|
||||
_sargs_begin_quote(c);
|
||||
continue;
|
||||
}
|
||||
_sargs_start_val();
|
||||
}
|
||||
else {
|
||||
/* separator */
|
||||
if (_sargs_is_separator(c)) {
|
||||
_sargs_expect_val();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* skip white space */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (_sargs_parsing_key()) {
|
||||
if (_sargs_is_whitespace(c) || _sargs_is_separator(c)) {
|
||||
/* end of key string */
|
||||
_sargs_end_key();
|
||||
if (_sargs_is_separator(c)) {
|
||||
_sargs_expect_val();
|
||||
}
|
||||
else {
|
||||
_sargs_expect_sep();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (_sargs_parsing_val()) {
|
||||
if (_sargs_in_quotes()) {
|
||||
/* when in quotes, whitespace is a normal character
|
||||
and a matching quote ends the value string
|
||||
*/
|
||||
if (_sargs_is_quote(c)) {
|
||||
_sargs_end_quote();
|
||||
_sargs_end_val();
|
||||
_sargs_expect_key();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (_sargs_is_whitespace(c)) {
|
||||
/* end of value string (no quotes) */
|
||||
_sargs_end_val();
|
||||
_sargs_expect_key();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_sargs_putc(c);
|
||||
}
|
||||
if (_sargs_parsing_key()) {
|
||||
_sargs_end_key();
|
||||
_sargs_expect_sep();
|
||||
}
|
||||
else if (_sargs_parsing_val() && !_sargs_in_quotes()) {
|
||||
_sargs_end_val();
|
||||
_sargs_expect_key();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_parse_cargs(int argc, const char** argv) {
|
||||
_sargs_expect_key();
|
||||
bool retval = true;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
retval &= _sargs_parse_carg(argv[i]);
|
||||
}
|
||||
_sargs.parse_state = 0;
|
||||
return retval;
|
||||
}
|
||||
#endif /* __EMSCRIPTEN__ */
|
||||
|
||||
/*-- EMSCRIPTEN IMPLEMENTATION -----------------------------------------------*/
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EMSCRIPTEN_KEEPALIVE void _sargs_add_kvp(const char* key, const char* val) {
|
||||
SOKOL_ASSERT(_sargs.valid && key && val);
|
||||
if (_sargs.num_args >= _sargs.max_args) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy key string */
|
||||
char c;
|
||||
_sargs.args[_sargs.num_args].key = _sargs.buf_pos;
|
||||
const char* ptr = key;
|
||||
while (0 != (c = *ptr++)) {
|
||||
_sargs_putc(c);
|
||||
}
|
||||
_sargs_putc(0);
|
||||
|
||||
/* copy value string */
|
||||
_sargs.args[_sargs.num_args].val = _sargs.buf_pos;
|
||||
ptr = val;
|
||||
while (0 != (c = *ptr++)) {
|
||||
_sargs_putc(c);
|
||||
}
|
||||
_sargs_putc(0);
|
||||
|
||||
_sargs.num_args++;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/* JS function to extract arguments from the page URL */
|
||||
EM_JS(void, sargs_js_parse_url, (void), {
|
||||
var params = new URLSearchParams(window.location.search).entries();
|
||||
for (var p = params.next(); !p.done; p = params.next()) {
|
||||
var key = p.value[0];
|
||||
var val = p.value[1];
|
||||
var res = ccall('_sargs_add_kvp', 'void', ['string','string'], [key,val]);
|
||||
}
|
||||
});
|
||||
|
||||
#endif /* EMSCRIPTEN */
|
||||
|
||||
/*== PUBLIC IMPLEMENTATION FUNCTIONS =========================================*/
|
||||
SOKOL_API_IMPL void sargs_setup(const sargs_desc* desc) {
|
||||
SOKOL_ASSERT(desc);
|
||||
memset(&_sargs, 0, sizeof(_sargs));
|
||||
_sargs.max_args = _sargs_def(desc->max_args, _SARGS_MAX_ARGS_DEF);
|
||||
_sargs.buf_size = _sargs_def(desc->buf_size, _SARGS_BUF_SIZE_DEF);
|
||||
SOKOL_ASSERT(_sargs.buf_size > 8);
|
||||
_sargs.args = (_sargs_kvp_t*) SOKOL_CALLOC(_sargs.max_args, sizeof(_sargs_kvp_t));
|
||||
_sargs.buf = (char*) SOKOL_CALLOC(_sargs.buf_size, sizeof(char));
|
||||
/* the first character in buf is reserved and always zero, this is the 'empty string' */
|
||||
_sargs.buf_pos = 1;
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
/* on emscripten, ignore argc/argv, and parse the page URL instead */
|
||||
sargs_js_parse_url();
|
||||
#else
|
||||
/* on native platform, parse argc/argv */
|
||||
_sargs_parse_cargs(desc->argc, (const char**) desc->argv);
|
||||
#endif
|
||||
_sargs.valid = true;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL void sargs_shutdown(void) {
|
||||
SOKOL_ASSERT(_sargs.valid);
|
||||
if (_sargs.args) {
|
||||
SOKOL_FREE(_sargs.args);
|
||||
_sargs.args = 0;
|
||||
}
|
||||
if (_sargs.buf) {
|
||||
SOKOL_FREE(_sargs.buf);
|
||||
_sargs.buf = 0;
|
||||
}
|
||||
_sargs.valid = false;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL bool sargs_isvalid(void) {
|
||||
return _sargs.valid;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL int sargs_find(const char* key) {
|
||||
SOKOL_ASSERT(_sargs.valid && key);
|
||||
for (int i = 0; i < _sargs.num_args; i++) {
|
||||
if (0 == strcmp(_sargs_str(_sargs.args[i].key), key)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL int sargs_num_args(void) {
|
||||
SOKOL_ASSERT(_sargs.valid);
|
||||
return _sargs.num_args;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL const char* sargs_key_at(int index) {
|
||||
SOKOL_ASSERT(_sargs.valid);
|
||||
if ((index >= 0) && (index < _sargs.num_args)) {
|
||||
return _sargs_str(_sargs.args[index].key);
|
||||
}
|
||||
else {
|
||||
/* index 0 is always the empty string */
|
||||
return _sargs_str(0);
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL const char* sargs_value_at(int index) {
|
||||
SOKOL_ASSERT(_sargs.valid);
|
||||
if ((index >= 0) && (index < _sargs.num_args)) {
|
||||
return _sargs_str(_sargs.args[index].val);
|
||||
}
|
||||
else {
|
||||
/* index 0 is always the empty string */
|
||||
return _sargs_str(0);
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL bool sargs_exists(const char* key) {
|
||||
SOKOL_ASSERT(_sargs.valid && key);
|
||||
return -1 != sargs_find(key);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL const char* sargs_value(const char* key) {
|
||||
SOKOL_ASSERT(_sargs.valid && key);
|
||||
return sargs_value_at(sargs_find(key));
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL const char* sargs_value_def(const char* key, const char* def) {
|
||||
SOKOL_ASSERT(_sargs.valid && key && def);
|
||||
int arg_index = sargs_find(key);
|
||||
if (-1 != arg_index) {
|
||||
return sargs_value_at(arg_index);
|
||||
}
|
||||
else {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL bool sargs_equals(const char* key, const char* val) {
|
||||
SOKOL_ASSERT(_sargs.valid && key && val);
|
||||
return 0 == strcmp(sargs_value(key), val);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL bool sargs_boolean(const char* key) {
|
||||
const char* val = sargs_value(key);
|
||||
return (0 == strcmp("true", val)) ||
|
||||
(0 == strcmp("yes", val)) ||
|
||||
(0 == strcmp("on", val));
|
||||
}
|
||||
|
||||
#endif /* SOKOL_IMPL */
|
1726
3rd/sokol/sokol_audio.h
Normal file
1726
3rd/sokol/sokol_audio.h
Normal file
File diff suppressed because it is too large
Load Diff
2492
3rd/sokol/sokol_fetch.h
Normal file
2492
3rd/sokol/sokol_fetch.h
Normal file
File diff suppressed because it is too large
Load Diff
11662
3rd/sokol/sokol_gfx.h
Normal file
11662
3rd/sokol/sokol_gfx.h
Normal file
File diff suppressed because it is too large
Load Diff
277
3rd/sokol/sokol_time.h
Normal file
277
3rd/sokol/sokol_time.h
Normal file
@ -0,0 +1,277 @@
|
||||
#ifndef SOKOL_TIME_INCLUDED
|
||||
/*
|
||||
sokol_time.h -- simple cross-platform time measurement
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
Optionally provide the following defines with your own implementations:
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
If sokol_time.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
void stm_setup();
|
||||
Call once before any other functions to initialize sokol_time
|
||||
(this calls for instance QueryPerformanceFrequency on Windows)
|
||||
|
||||
uint64_t stm_now();
|
||||
Get current point in time in unspecified 'ticks'. The value that
|
||||
is returned has no relation to the 'wall-clock' time and is
|
||||
not in a specific time unit, it is only useful to compute
|
||||
time differences.
|
||||
|
||||
uint64_t stm_diff(uint64_t new, uint64_t old);
|
||||
Computes the time difference between new and old. This will always
|
||||
return a positive, non-zero value.
|
||||
|
||||
uint64_t stm_since(uint64_t start);
|
||||
Takes the current time, and returns the elapsed time since start
|
||||
(this is a shortcut for "stm_diff(stm_now(), start)")
|
||||
|
||||
uint64_t stm_laptime(uint64_t* last_time);
|
||||
This is useful for measuring frame time and other recurring
|
||||
events. It takes the current time, returns the time difference
|
||||
to the value in last_time, and stores the current time in
|
||||
last_time for the next call. If the value in last_time is 0,
|
||||
the return value will be zero (this usually happens on the
|
||||
very first call).
|
||||
|
||||
Use the following functions to convert a duration in ticks into
|
||||
useful time units:
|
||||
|
||||
double stm_sec(uint64_t ticks);
|
||||
double stm_ms(uint64_t ticks);
|
||||
double stm_us(uint64_t ticks);
|
||||
double stm_ns(uint64_t ticks);
|
||||
Converts a tick value into seconds, milliseconds, microseconds
|
||||
or nanoseconds. Note that not all platforms will have nanosecond
|
||||
or even microsecond precision.
|
||||
|
||||
Uses the following time measurement functions under the hood:
|
||||
|
||||
Windows: QueryPerformanceFrequency() / QueryPerformanceCounter()
|
||||
MacOS/iOS: mach_absolute_time()
|
||||
emscripten: performance.now()
|
||||
Linux+others: clock_gettime(CLOCK_MONOTONIC)
|
||||
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_TIME_INCLUDED (1)
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef SOKOL_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_IMPL)
|
||||
#define SOKOL_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SOKOL_API_DECL void stm_setup(void);
|
||||
SOKOL_API_DECL uint64_t stm_now(void);
|
||||
SOKOL_API_DECL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks);
|
||||
SOKOL_API_DECL uint64_t stm_since(uint64_t start_ticks);
|
||||
SOKOL_API_DECL uint64_t stm_laptime(uint64_t* last_time);
|
||||
SOKOL_API_DECL double stm_sec(uint64_t ticks);
|
||||
SOKOL_API_DECL double stm_ms(uint64_t ticks);
|
||||
SOKOL_API_DECL double stm_us(uint64_t ticks);
|
||||
SOKOL_API_DECL double stm_ns(uint64_t ticks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif // SOKOL_TIME_INCLUDED
|
||||
|
||||
/*-- IMPLEMENTATION ----------------------------------------------------------*/
|
||||
#ifdef SOKOL_IMPL
|
||||
#define SOKOL_TIME_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
#ifndef _SOKOL_PRIVATE
|
||||
#if defined(__GNUC__)
|
||||
#define _SOKOL_PRIVATE __attribute__((unused)) static
|
||||
#else
|
||||
#define _SOKOL_PRIVATE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
LARGE_INTEGER freq;
|
||||
LARGE_INTEGER start;
|
||||
} _stm_state_t;
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#include <mach/mach_time.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
mach_timebase_info_data_t timebase;
|
||||
uint64_t start;
|
||||
} _stm_state_t;
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#include <emscripten/emscripten.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
double start;
|
||||
} _stm_state_t;
|
||||
#else /* anything else, this will need more care for non-Linux platforms */
|
||||
#ifdef ESP8266
|
||||
// On the ESP8266, clock_gettime ignores the first argument and CLOCK_MONOTONIC isn't defined
|
||||
#define CLOCK_MONOTONIC 0
|
||||
#endif
|
||||
#include <time.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
uint64_t start;
|
||||
} _stm_state_t;
|
||||
#endif
|
||||
static _stm_state_t _stm;
|
||||
|
||||
/* prevent 64-bit overflow when computing relative timestamp
|
||||
see https://gist.github.com/jspohr/3dc4f00033d79ec5bdaf67bc46c813e3
|
||||
*/
|
||||
#if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__))
|
||||
_SOKOL_PRIVATE int64_t int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
|
||||
int64_t q = value / denom;
|
||||
int64_t r = value % denom;
|
||||
return q * numer + r * numer / denom;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
EM_JS(double, stm_js_perfnow, (void), {
|
||||
return performance.now();
|
||||
});
|
||||
#endif
|
||||
|
||||
SOKOL_API_IMPL void stm_setup(void) {
|
||||
memset(&_stm, 0, sizeof(_stm));
|
||||
_stm.initialized = 0xABCDABCD;
|
||||
#if defined(_WIN32)
|
||||
QueryPerformanceFrequency(&_stm.freq);
|
||||
QueryPerformanceCounter(&_stm.start);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
mach_timebase_info(&_stm.timebase);
|
||||
_stm.start = mach_absolute_time();
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
_stm.start = stm_js_perfnow();
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
_stm.start = (uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_now(void) {
|
||||
SOKOL_ASSERT(_stm.initialized == 0xABCDABCD);
|
||||
uint64_t now;
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER qpc_t;
|
||||
QueryPerformanceCounter(&qpc_t);
|
||||
now = int64_muldiv(qpc_t.QuadPart - _stm.start.QuadPart, 1000000000, _stm.freq.QuadPart);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
const uint64_t mach_now = mach_absolute_time() - _stm.start;
|
||||
now = int64_muldiv(mach_now, _stm.timebase.numer, _stm.timebase.denom);
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
double js_now = stm_js_perfnow() - _stm.start;
|
||||
SOKOL_ASSERT(js_now >= 0.0);
|
||||
now = (uint64_t) (js_now * 1000000.0);
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ((uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec) - _stm.start;
|
||||
#endif
|
||||
return now;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks) {
|
||||
if (new_ticks > old_ticks) {
|
||||
return new_ticks - old_ticks;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_since(uint64_t start_ticks) {
|
||||
return stm_diff(stm_now(), start_ticks);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_laptime(uint64_t* last_time) {
|
||||
SOKOL_ASSERT(last_time);
|
||||
uint64_t dt = 0;
|
||||
uint64_t now = stm_now();
|
||||
if (0 != *last_time) {
|
||||
dt = stm_diff(now, *last_time);
|
||||
}
|
||||
*last_time = now;
|
||||
return dt;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_sec(uint64_t ticks) {
|
||||
return (double)ticks / 1000000000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_ms(uint64_t ticks) {
|
||||
return (double)ticks / 1000000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_us(uint64_t ticks) {
|
||||
return (double)ticks / 1000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_ns(uint64_t ticks) {
|
||||
return (double)ticks;
|
||||
}
|
||||
#endif /* SOKOL_IMPL */
|
||||
|
17
3rd/sokol/util/README.md
Normal file
17
3rd/sokol/util/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Sokol Utility Headers
|
||||
|
||||
These are optional utility headers on top of the Sokol headers. Unlike the
|
||||
'core headers' they are not standalone but depend on other Sokol headers
|
||||
and sometimes also external libraries.
|
||||
|
||||
### What's in here:
|
||||
|
||||
- **sokol_imgui.h**: implements a renderer for [Dear ImGui](https://github.com/ocornut/imgui) on top of sokol_gfx.h and sokol_app.h (the latter being optional if you do your own input-forwarding to ImGui), the implementation
|
||||
can be compiled as C++ or C.
|
||||
- **sokol_gfx_imgui.h**: a debug-inspection UI for sokol_gfx.h, this hooks into the sokol-gfx API and lets you inspect resource objects and captured API calls
|
||||
- **sokol_gl.h**: an OpenGL 1.x style immediate-mode rendering API
|
||||
on top of sokol_gfx.h
|
||||
- **sokol_fontstash.h**: a renderer for [fontstash.h](https://github.com/memononen/fontstash) on
|
||||
on top of sokol_gl.h
|
||||
|
||||
See the embedded header-documentation for build- and usage-details.
|
789
3rd/sokol/util/sokol_fontstash.h
Normal file
789
3rd/sokol/util/sokol_fontstash.h
Normal file
@ -0,0 +1,789 @@
|
||||
#ifndef SOKOL_FONTSTASH_INCLUDED
|
||||
/*
|
||||
sokol_fontstash.h -- renderer for https://github.com/memononen/fontstash
|
||||
on top of sokol_gl.h
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
|
||||
#define SOKOL_FONTSTASH_IMPL
|
||||
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
The following defines are used by the implementation to select the
|
||||
platform-specific embedded shader code (these are the same defines as
|
||||
used by sokol_gfx.h and sokol_app.h):
|
||||
|
||||
SOKOL_GLCORE33
|
||||
SOKOL_GLES2
|
||||
SOKOL_GLES3
|
||||
SOKOL_D3D11
|
||||
SOKOL_METAL
|
||||
|
||||
...optionally provide the following macros to override defaults:
|
||||
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_MALLOC(s) - your own malloc function (default: malloc(s))
|
||||
SOKOL_FREE(p) - your own free function (default: free(p))
|
||||
SOKOL_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
SOKOL_LOG(msg) - your own logging function (default: puts(msg))
|
||||
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
|
||||
|
||||
Include the following headers before including sokol_fontstash.h:
|
||||
|
||||
sokol_gfx.h
|
||||
|
||||
Additionally include the following headers for including the sokol_fontstash.h
|
||||
implementation:
|
||||
|
||||
sokol_gl.h
|
||||
|
||||
HOW TO
|
||||
======
|
||||
--- First initialize sokol-gfx and sokol-gl as usual:
|
||||
|
||||
sg_setup(&(sg_desc){...});
|
||||
sgl_setup(&(sgl_desc){...});
|
||||
|
||||
--- Create at least one fontstash context with sfons_create() (this replaces
|
||||
glfonsCreate() from fontstash.h's example GL renderer:
|
||||
|
||||
FONScontext* ctx = sfons_create(atlas_width, atlas_height, FONS_ZERO_TOPLEFT);
|
||||
|
||||
Each FONScontext manages one font atlas texture which can hold rasterized
|
||||
glyphs for multiple fonts.
|
||||
|
||||
--- From here on, use fontstash.h's functions "as usual" to add TTF
|
||||
font data and draw text. Note that (just like with sokol-gl), text
|
||||
rendering can happen anywhere in the frame, not only inside
|
||||
a sokol-gfx rendering pass.
|
||||
|
||||
--- You can use the helper function
|
||||
|
||||
uint32_t sfons_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
|
||||
To convert a 0..255 RGBA color into a packed uint32_t color value
|
||||
expected by fontstash.h.
|
||||
|
||||
--- Once per frame before calling sgl_draw(), call:
|
||||
|
||||
sfons_flush(FONScontext* ctx)
|
||||
|
||||
...this will update the dynamic sokol-gfx texture with the latest font
|
||||
atlas content.
|
||||
|
||||
--- To actually render the text (and any other sokol-gl draw commands),
|
||||
call sgl_draw() inside a sokol-gfx frame.
|
||||
|
||||
--- NOTE that you can mix fontstash.h calls with sokol-gl calls to mix
|
||||
text rendering with sokol-gl rendering. You can also use
|
||||
sokol-gl's matrix stack to position fontstash.h text in 3D.
|
||||
|
||||
--- finally on application shutdown, call:
|
||||
|
||||
sfons_shutdown()
|
||||
|
||||
before sgl_shutdown() and sg_shutdown()
|
||||
|
||||
|
||||
WHAT HAPPENS UNDER THE HOOD:
|
||||
============================
|
||||
|
||||
sfons_create():
|
||||
- creates a sokol-gfx shader compatible with sokol-gl
|
||||
- creates an sgl_pipeline object with alpha-blending using
|
||||
this shader
|
||||
- creates a 1-byte-per-pixel font atlas texture via sokol-gfx
|
||||
(pixel format SG_PIXELFORMAT_R8)
|
||||
|
||||
fonsDrawText():
|
||||
- this will call the following sequence of sokol-gl functions:
|
||||
|
||||
sgl_enable_texture();
|
||||
sgl_texture(...);
|
||||
sgl_push_pipeline();
|
||||
sgl_load_pipeline(...);
|
||||
sgl_begin_triangles();
|
||||
for each vertex:
|
||||
sg_v2f_t2f_c1i(...);
|
||||
sgl_end();
|
||||
sgl_pop_pipeline();
|
||||
sgl_disable_texture();
|
||||
|
||||
- note that sokol-gl will merge several sgl_*_begin/sgl_end pairs
|
||||
into a single draw call if no relevant state has changed, typically
|
||||
all calls to fonsDrawText() will be merged into a single draw call
|
||||
as long as all calls use the same FONScontext
|
||||
|
||||
sfons_flush():
|
||||
- this will call sg_update_image() on the font atlas texture
|
||||
if fontstash.h has added any rasterized glyphs since the last
|
||||
frame
|
||||
|
||||
sfons_shutdown():
|
||||
- destroy the font atlas texture, sgl_pipeline and sg_shader objects
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_FONTSTASH_INCLUDED (1)
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(SOKOL_GFX_INCLUDED)
|
||||
#error "Please include sokol_gfx.h before sokol_fontstash.h"
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_IMPL)
|
||||
#define SOKOL_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SOKOL_API_DECL FONScontext* sfons_create(int width, int height, int flags);
|
||||
SOKOL_API_DECL void sfons_destroy(FONScontext* ctx);
|
||||
SOKOL_API_DECL void sfons_flush(FONScontext* ctx);
|
||||
SOKOL_API_DECL uint32_t sfons_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* SOKOL_FONTSTASH_INCLUDED */
|
||||
|
||||
/*-- IMPLEMENTATION ----------------------------------------------------------*/
|
||||
#ifdef SOKOL_FONTSTASH_IMPL
|
||||
#define SOKOL_FONTSTASH_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset, memcpy */
|
||||
|
||||
#if !defined(SOKOL_GL_INCLUDED)
|
||||
#error "Please include sokol_gl.h before sokol_fontstash.h"
|
||||
#endif
|
||||
#if !defined(FONS_H)
|
||||
#error "Please include fontstash.h before sokol_fontstash.h"
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define SOKOL_DEBUG (1)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
#ifndef SOKOL_MALLOC
|
||||
#include <stdlib.h>
|
||||
#define SOKOL_MALLOC(s) malloc(s)
|
||||
#define SOKOL_FREE(p) free(p)
|
||||
#endif
|
||||
#ifndef SOKOL_LOG
|
||||
#ifdef SOKOL_DEBUG
|
||||
#include <stdio.h>
|
||||
#define SOKOL_LOG(s) { SOKOL_ASSERT(s); puts(s); }
|
||||
#else
|
||||
#define SOKOL_LOG(s)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SOKOL_UNREACHABLE
|
||||
#define SOKOL_UNREACHABLE SOKOL_ASSERT(false)
|
||||
#endif
|
||||
|
||||
#if defined(SOKOL_GLCORE33)
|
||||
static const char* _sfons_vs_src =
|
||||
"#version 330\n"
|
||||
"uniform mat4 mvp;\n"
|
||||
"uniform mat4 tm;\n"
|
||||
"in vec4 position;\n"
|
||||
"in vec2 texcoord0;\n"
|
||||
"in vec4 color0;\n"
|
||||
"out vec4 uv;\n"
|
||||
"out vec4 color;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = mvp * position;\n"
|
||||
" uv = tm * vec4(texcoord0, 0.0, 1.0);\n"
|
||||
" color = color0;\n"
|
||||
"}\n";
|
||||
static const char* _sfons_fs_src =
|
||||
"#version 330\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"in vec4 uv;\n"
|
||||
"in vec4 color;\n"
|
||||
"out vec4 frag_color;\n"
|
||||
"void main() {\n"
|
||||
" frag_color = vec4(1.0, 1.0, 1.0, texture(tex, uv.xy).r) * color;\n"
|
||||
"}\n";
|
||||
#elif defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
|
||||
static const char* _sfons_vs_src =
|
||||
"uniform mat4 mvp;\n"
|
||||
"uniform mat4 tm;\n"
|
||||
"attribute vec4 position;\n"
|
||||
"attribute vec2 texcoord0;\n"
|
||||
"attribute vec4 color0;\n"
|
||||
"varying vec4 uv;\n"
|
||||
"varying vec4 color;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = mvp * position;\n"
|
||||
" uv = tm * vec4(texcoord0, 0.0, 1.0);\n"
|
||||
" color = color0;\n"
|
||||
"}\n";
|
||||
static const char* _sfons_fs_src =
|
||||
"precision mediump float;\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"varying vec4 uv;\n"
|
||||
"varying vec4 color;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = vec4(1.0, 1.0, 1.0, texture2D(tex, uv.xy).r) * color;\n"
|
||||
"}\n";
|
||||
#elif defined(SOKOL_METAL)
|
||||
static const char* _sfons_vs_src =
|
||||
"#include <metal_stdlib>\n"
|
||||
"using namespace metal;\n"
|
||||
"struct params_t {\n"
|
||||
" float4x4 mvp;\n"
|
||||
" float4x4 tm;\n"
|
||||
"};\n"
|
||||
"struct vs_in {\n"
|
||||
" float4 pos [[attribute(0)]];\n"
|
||||
" float2 uv [[attribute(1)]];\n"
|
||||
" float4 color [[attribute(2)]];\n"
|
||||
"};\n"
|
||||
"struct vs_out {\n"
|
||||
" float4 pos [[position]];\n"
|
||||
" float4 uv;\n"
|
||||
" float4 color;\n"
|
||||
"};\n"
|
||||
"vertex vs_out _main(vs_in in [[stage_in]], constant params_t& params [[buffer(0)]]) {\n"
|
||||
" vs_out out;\n"
|
||||
" out.pos = params.mvp * in.pos;\n"
|
||||
" out.uv = params.tm * float4(in.uv, 0.0, 1.0);\n"
|
||||
" out.color = in.color;\n"
|
||||
" return out;\n"
|
||||
"}\n";
|
||||
static const char* _sfons_fs_src =
|
||||
"#include <metal_stdlib>\n"
|
||||
"using namespace metal;\n"
|
||||
"struct fs_in {\n"
|
||||
" float4 uv;\n"
|
||||
" float4 color;\n"
|
||||
"};\n"
|
||||
"fragment float4 _main(fs_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]]) {\n"
|
||||
" return float4(1.0, 1.0, 1.0, tex.sample(smp, in.uv.xy).r) * in.color;\n"
|
||||
"}\n";
|
||||
#elif defined(SOKOL_D3D11)
|
||||
/*
|
||||
Shader blobs for D3D11, compiled with:
|
||||
|
||||
fxc.exe /T vs_4_0 /Fh vs.h /Gec /O3 vs.hlsl
|
||||
fxc.exe /T ps_4_0 /Fh fs.h /Gec /O3 fs.hlsl
|
||||
|
||||
Vertex shader source:
|
||||
|
||||
cbuffer params: register(b0) {
|
||||
float4x4 mvp;
|
||||
float4x4 tm;
|
||||
};
|
||||
struct vs_in {
|
||||
float4 pos: POSITION;
|
||||
float2 uv: TEXCOORD0;
|
||||
float4 color: COLOR0;
|
||||
};
|
||||
struct vs_out {
|
||||
float4 uv: TEXCOORD0;
|
||||
float4 color: COLOR0;
|
||||
float4 pos: SV_Position;
|
||||
};
|
||||
vs_out main(vs_in inp) {
|
||||
vs_out outp;
|
||||
outp.pos = mul(mvp, inp.pos);
|
||||
outp.uv = mul(tm, float4(inp.uv, 0.0, 1.0));
|
||||
outp.color = inp.color;
|
||||
return outp;
|
||||
};
|
||||
|
||||
Pixel shader source:
|
||||
|
||||
Texture2D<float4> tex: register(t0);
|
||||
sampler smp: register(s0);
|
||||
float4 main(float4 uv: TEXCOORD0, float4 color: COLOR0): SV_Target0 {
|
||||
return float4(1.0, 1.0, 1.0, tex.Sample(smp, uv.xy).r) * color;
|
||||
}
|
||||
*/
|
||||
static const uint8_t _sfons_vs_bin[] = {
|
||||
68, 88, 66, 67, 89, 173,
|
||||
124, 225, 74, 102, 159, 55,
|
||||
47, 64, 241, 32, 31, 107,
|
||||
240, 204, 1, 0, 0, 0,
|
||||
244, 3, 0, 0, 5, 0,
|
||||
0, 0, 52, 0, 0, 0,
|
||||
8, 1, 0, 0, 120, 1,
|
||||
0, 0, 236, 1, 0, 0,
|
||||
120, 3, 0, 0, 82, 68,
|
||||
69, 70, 204, 0, 0, 0,
|
||||
1, 0, 0, 0, 68, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
28, 0, 0, 0, 0, 4,
|
||||
254, 255, 0, 17, 0, 0,
|
||||
163, 0, 0, 0, 60, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
112, 97, 114, 97, 109, 115,
|
||||
0, 171, 60, 0, 0, 0,
|
||||
2, 0, 0, 0, 92, 0,
|
||||
0, 0, 128, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 140, 0, 0, 0,
|
||||
0, 0, 0, 0, 64, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
144, 0, 0, 0, 0, 0,
|
||||
0, 0, 160, 0, 0, 0,
|
||||
64, 0, 0, 0, 64, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
144, 0, 0, 0, 0, 0,
|
||||
0, 0, 109, 118, 112, 0,
|
||||
3, 0, 3, 0, 4, 0,
|
||||
4, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 116, 109,
|
||||
0, 77, 105, 99, 114, 111,
|
||||
115, 111, 102, 116, 32, 40,
|
||||
82, 41, 32, 72, 76, 83,
|
||||
76, 32, 83, 104, 97, 100,
|
||||
101, 114, 32, 67, 111, 109,
|
||||
112, 105, 108, 101, 114, 32,
|
||||
49, 48, 46, 49, 0, 171,
|
||||
73, 83, 71, 78, 104, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
8, 0, 0, 0, 80, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
15, 15, 0, 0, 89, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
3, 3, 0, 0, 98, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
15, 15, 0, 0, 80, 79,
|
||||
83, 73, 84, 73, 79, 78,
|
||||
0, 84, 69, 88, 67, 79,
|
||||
79, 82, 68, 0, 67, 79,
|
||||
76, 79, 82, 0, 79, 83,
|
||||
71, 78, 108, 0, 0, 0,
|
||||
3, 0, 0, 0, 8, 0,
|
||||
0, 0, 80, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 15, 0,
|
||||
0, 0, 89, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
1, 0, 0, 0, 15, 0,
|
||||
0, 0, 95, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
2, 0, 0, 0, 15, 0,
|
||||
0, 0, 84, 69, 88, 67,
|
||||
79, 79, 82, 68, 0, 67,
|
||||
79, 76, 79, 82, 0, 83,
|
||||
86, 95, 80, 111, 115, 105,
|
||||
116, 105, 111, 110, 0, 171,
|
||||
83, 72, 68, 82, 132, 1,
|
||||
0, 0, 64, 0, 1, 0,
|
||||
97, 0, 0, 0, 89, 0,
|
||||
0, 4, 70, 142, 32, 0,
|
||||
0, 0, 0, 0, 8, 0,
|
||||
0, 0, 95, 0, 0, 3,
|
||||
242, 16, 16, 0, 0, 0,
|
||||
0, 0, 95, 0, 0, 3,
|
||||
50, 16, 16, 0, 1, 0,
|
||||
0, 0, 95, 0, 0, 3,
|
||||
242, 16, 16, 0, 2, 0,
|
||||
0, 0, 101, 0, 0, 3,
|
||||
242, 32, 16, 0, 0, 0,
|
||||
0, 0, 101, 0, 0, 3,
|
||||
242, 32, 16, 0, 1, 0,
|
||||
0, 0, 103, 0, 0, 4,
|
||||
242, 32, 16, 0, 2, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
104, 0, 0, 2, 1, 0,
|
||||
0, 0, 56, 0, 0, 8,
|
||||
242, 0, 16, 0, 0, 0,
|
||||
0, 0, 86, 21, 16, 0,
|
||||
1, 0, 0, 0, 70, 142,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
5, 0, 0, 0, 50, 0,
|
||||
0, 10, 242, 0, 16, 0,
|
||||
0, 0, 0, 0, 70, 142,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
4, 0, 0, 0, 6, 16,
|
||||
16, 0, 1, 0, 0, 0,
|
||||
70, 14, 16, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 8,
|
||||
242, 32, 16, 0, 0, 0,
|
||||
0, 0, 70, 14, 16, 0,
|
||||
0, 0, 0, 0, 70, 142,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
7, 0, 0, 0, 54, 0,
|
||||
0, 5, 242, 32, 16, 0,
|
||||
1, 0, 0, 0, 70, 30,
|
||||
16, 0, 2, 0, 0, 0,
|
||||
56, 0, 0, 8, 242, 0,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
86, 21, 16, 0, 0, 0,
|
||||
0, 0, 70, 142, 32, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 50, 0, 0, 10,
|
||||
242, 0, 16, 0, 0, 0,
|
||||
0, 0, 70, 142, 32, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 6, 16, 16, 0,
|
||||
0, 0, 0, 0, 70, 14,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
50, 0, 0, 10, 242, 0,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
70, 142, 32, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
166, 26, 16, 0, 0, 0,
|
||||
0, 0, 70, 14, 16, 0,
|
||||
0, 0, 0, 0, 50, 0,
|
||||
0, 10, 242, 32, 16, 0,
|
||||
2, 0, 0, 0, 70, 142,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 246, 31,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
70, 14, 16, 0, 0, 0,
|
||||
0, 0, 62, 0, 0, 1,
|
||||
83, 84, 65, 84, 116, 0,
|
||||
0, 0, 9, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 6, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
static uint8_t _sfons_fs_bin[] = {
|
||||
68, 88, 66, 67, 180, 53,
|
||||
115, 174, 239, 17, 254, 112,
|
||||
63, 104, 217, 123, 150, 145,
|
||||
179, 27, 1, 0, 0, 0,
|
||||
120, 2, 0, 0, 5, 0,
|
||||
0, 0, 52, 0, 0, 0,
|
||||
200, 0, 0, 0, 24, 1,
|
||||
0, 0, 76, 1, 0, 0,
|
||||
252, 1, 0, 0, 82, 68,
|
||||
69, 70, 140, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
28, 0, 0, 0, 0, 4,
|
||||
255, 255, 0, 17, 0, 0,
|
||||
100, 0, 0, 0, 92, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
96, 0, 0, 0, 2, 0,
|
||||
0, 0, 5, 0, 0, 0,
|
||||
4, 0, 0, 0, 255, 255,
|
||||
255, 255, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 13, 0,
|
||||
0, 0, 115, 109, 112, 0,
|
||||
116, 101, 120, 0, 77, 105,
|
||||
99, 114, 111, 115, 111, 102,
|
||||
116, 32, 40, 82, 41, 32,
|
||||
72, 76, 83, 76, 32, 83,
|
||||
104, 97, 100, 101, 114, 32,
|
||||
67, 111, 109, 112, 105, 108,
|
||||
101, 114, 32, 49, 48, 46,
|
||||
49, 0, 73, 83, 71, 78,
|
||||
72, 0, 0, 0, 2, 0,
|
||||
0, 0, 8, 0, 0, 0,
|
||||
56, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 0, 0,
|
||||
0, 0, 15, 3, 0, 0,
|
||||
65, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 1, 0,
|
||||
0, 0, 15, 15, 0, 0,
|
||||
84, 69, 88, 67, 79, 79,
|
||||
82, 68, 0, 67, 79, 76,
|
||||
79, 82, 0, 171, 79, 83,
|
||||
71, 78, 44, 0, 0, 0,
|
||||
1, 0, 0, 0, 8, 0,
|
||||
0, 0, 32, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 15, 0,
|
||||
0, 0, 83, 86, 95, 84,
|
||||
97, 114, 103, 101, 116, 0,
|
||||
171, 171, 83, 72, 68, 82,
|
||||
168, 0, 0, 0, 64, 0,
|
||||
0, 0, 42, 0, 0, 0,
|
||||
90, 0, 0, 3, 0, 96,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
88, 24, 0, 4, 0, 112,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
85, 85, 0, 0, 98, 16,
|
||||
0, 3, 50, 16, 16, 0,
|
||||
0, 0, 0, 0, 98, 16,
|
||||
0, 3, 242, 16, 16, 0,
|
||||
1, 0, 0, 0, 101, 0,
|
||||
0, 3, 242, 32, 16, 0,
|
||||
0, 0, 0, 0, 104, 0,
|
||||
0, 2, 1, 0, 0, 0,
|
||||
69, 0, 0, 9, 242, 0,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
70, 16, 16, 0, 0, 0,
|
||||
0, 0, 150, 115, 16, 0,
|
||||
0, 0, 0, 0, 0, 96,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
54, 0, 0, 5, 18, 0,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
1, 64, 0, 0, 0, 0,
|
||||
128, 63, 56, 0, 0, 7,
|
||||
242, 32, 16, 0, 0, 0,
|
||||
0, 0, 6, 12, 16, 0,
|
||||
0, 0, 0, 0, 70, 30,
|
||||
16, 0, 1, 0, 0, 0,
|
||||
62, 0, 0, 1, 83, 84,
|
||||
65, 84, 116, 0, 0, 0,
|
||||
4, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0
|
||||
};
|
||||
#elif defined(SOKOL_DUMMY_BACKEND)
|
||||
static const char* _sfons_vs_src = "";
|
||||
static const char* _sfons_fs_src = "";
|
||||
#endif
|
||||
|
||||
typedef struct _sfons_t {
|
||||
sg_shader shd;
|
||||
sgl_pipeline pip;
|
||||
sg_image img;
|
||||
int width, height;
|
||||
bool img_dirty;
|
||||
} _sfons_t;
|
||||
|
||||
static int _sfons_render_create(void* user_ptr, int width, int height) {
|
||||
SOKOL_ASSERT(user_ptr && (width > 8) && (height > 8));
|
||||
_sfons_t* sfons = (_sfons_t*) user_ptr;
|
||||
|
||||
/* sokol-gl compatible shader which treats RED channel as alpha */
|
||||
if (sfons->shd.id == SG_INVALID_ID) {
|
||||
sg_shader_desc shd_desc;
|
||||
memset(&shd_desc, 0, sizeof(shd_desc));
|
||||
shd_desc.attrs[0].name = "position";
|
||||
shd_desc.attrs[1].name = "texcoord0";
|
||||
shd_desc.attrs[2].name = "color0";
|
||||
shd_desc.attrs[0].sem_name = "POSITION";
|
||||
shd_desc.attrs[1].sem_name = "TEXCOORD";
|
||||
shd_desc.attrs[2].sem_name = "COLOR";
|
||||
sg_shader_uniform_block_desc* ub = &shd_desc.vs.uniform_blocks[0];
|
||||
ub->size = 128;
|
||||
ub->uniforms[0].name = "mvp";
|
||||
ub->uniforms[0].type = SG_UNIFORMTYPE_MAT4;
|
||||
ub->uniforms[1].name = "tm";
|
||||
ub->uniforms[1].type = SG_UNIFORMTYPE_MAT4;
|
||||
shd_desc.fs.images[0].name = "tex";
|
||||
shd_desc.fs.images[0].type = SG_IMAGETYPE_2D;
|
||||
#if defined(SOKOL_D3D11)
|
||||
shd_desc.vs.byte_code = _sfons_vs_bin;
|
||||
shd_desc.vs.byte_code_size = sizeof(_sfons_vs_bin);
|
||||
shd_desc.fs.byte_code = _sfons_fs_bin;
|
||||
shd_desc.fs.byte_code_size = sizeof(_sfons_fs_bin);
|
||||
#else
|
||||
shd_desc.vs.source = _sfons_vs_src;
|
||||
shd_desc.fs.source = _sfons_fs_src;
|
||||
#endif
|
||||
shd_desc.label = "sfons-shader";
|
||||
sfons->shd = sg_make_shader(&shd_desc);
|
||||
}
|
||||
|
||||
/* sokol-gl pipeline object */
|
||||
if (sfons->pip.id == SG_INVALID_ID) {
|
||||
sg_pipeline_desc pip_desc;
|
||||
memset(&pip_desc, 0, sizeof(pip_desc));
|
||||
pip_desc.shader = sfons->shd;
|
||||
pip_desc.blend.enabled = true;
|
||||
pip_desc.blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA;
|
||||
pip_desc.blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
sfons->pip = sgl_make_pipeline(&pip_desc);
|
||||
}
|
||||
|
||||
/* create or re-create font atlas texture */
|
||||
if (sfons->img.id != SG_INVALID_ID) {
|
||||
sg_destroy_image(sfons->img);
|
||||
sfons->img.id = SG_INVALID_ID;
|
||||
}
|
||||
sfons->width = width;
|
||||
sfons->height = height;
|
||||
|
||||
SOKOL_ASSERT(sfons->img.id == SG_INVALID_ID);
|
||||
sg_image_desc img_desc;
|
||||
memset(&img_desc, 0, sizeof(img_desc));
|
||||
img_desc.width = sfons->width;
|
||||
img_desc.height = sfons->height;
|
||||
img_desc.min_filter = SG_FILTER_LINEAR;
|
||||
img_desc.mag_filter = SG_FILTER_LINEAR;
|
||||
img_desc.usage = SG_USAGE_DYNAMIC;
|
||||
img_desc.pixel_format = SG_PIXELFORMAT_R8;
|
||||
sfons->img = sg_make_image(&img_desc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _sfons_render_resize(void* user_ptr, int width, int height) {
|
||||
return _sfons_render_create(user_ptr, width, height);
|
||||
}
|
||||
|
||||
static void _sfons_render_update(void* user_ptr, int* rect, const unsigned char* data) {
|
||||
SOKOL_ASSERT(user_ptr && rect && data);
|
||||
_sfons_t* sfons = (_sfons_t*) user_ptr;
|
||||
sfons->img_dirty = true;
|
||||
}
|
||||
|
||||
static void _sfons_render_draw(void* user_ptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts) {
|
||||
SOKOL_ASSERT(user_ptr && verts && tcoords && colors && (nverts > 0));
|
||||
_sfons_t* sfons = (_sfons_t*) user_ptr;
|
||||
sgl_enable_texture();
|
||||
sgl_texture(sfons->img);
|
||||
sgl_push_pipeline();
|
||||
sgl_load_pipeline(sfons->pip);
|
||||
sgl_begin_triangles();
|
||||
for (int i = 0; i < nverts; i++) {
|
||||
sgl_v2f_t2f_c1i(verts[2*i+0], verts[2*i+1], tcoords[2*i+0], tcoords[2*i+1], colors[i]);
|
||||
}
|
||||
sgl_end();
|
||||
sgl_pop_pipeline();
|
||||
sgl_disable_texture();
|
||||
}
|
||||
|
||||
static void _sfons_render_delete(void* user_ptr) {
|
||||
SOKOL_ASSERT(user_ptr);
|
||||
_sfons_t* sfons = (_sfons_t*) user_ptr;
|
||||
if (sfons->img.id != SG_INVALID_ID) {
|
||||
sg_destroy_image(sfons->img);
|
||||
sfons->img.id = SG_INVALID_ID;
|
||||
}
|
||||
if (sfons->pip.id != SG_INVALID_ID) {
|
||||
sgl_destroy_pipeline(sfons->pip);
|
||||
sfons->pip.id = SG_INVALID_ID;
|
||||
}
|
||||
if (sfons->shd.id != SG_INVALID_ID) {
|
||||
sg_destroy_shader(sfons->shd);
|
||||
sfons->shd.id = SG_INVALID_ID;
|
||||
}
|
||||
SOKOL_FREE(sfons);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL FONScontext* sfons_create(int width, int height, int flags) {
|
||||
SOKOL_ASSERT((width > 0) && (height > 0));
|
||||
FONSparams params;
|
||||
_sfons_t* sfons = (_sfons_t*) SOKOL_MALLOC(sizeof(_sfons_t));
|
||||
memset(sfons, 0, sizeof(_sfons_t));
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.width = width;
|
||||
params.height = height;
|
||||
params.flags = (unsigned char) flags;
|
||||
params.renderCreate = _sfons_render_create;
|
||||
params.renderResize = _sfons_render_resize;
|
||||
params.renderUpdate = _sfons_render_update;
|
||||
params.renderDraw = _sfons_render_draw;
|
||||
params.renderDelete = _sfons_render_delete;
|
||||
params.userPtr = sfons;
|
||||
return fonsCreateInternal(¶ms);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL void sfons_destroy(FONScontext* ctx) {
|
||||
SOKOL_ASSERT(ctx);
|
||||
fonsDeleteInternal(ctx);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL void sfons_flush(FONScontext* ctx) {
|
||||
SOKOL_ASSERT(ctx && ctx->params.userPtr);
|
||||
_sfons_t* sfons = (_sfons_t*) ctx->params.userPtr;
|
||||
if (sfons->img_dirty) {
|
||||
sfons->img_dirty = false;
|
||||
sg_image_content content;
|
||||
memset(&content, 0, sizeof(content));
|
||||
content.subimage[0][0].ptr = ctx->texData;
|
||||
content.subimage[0][0].size = sfons->width * sfons->height;
|
||||
sg_update_image(sfons->img, &content);
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint32_t sfons_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
return (r) | (g<<8) | (b<<16) | (a<<24);
|
||||
}
|
||||
|
||||
#endif /* SOKOL_FONTSTASH_IMPL */
|
3648
3rd/sokol/util/sokol_gfx_imgui.h
Normal file
3648
3rd/sokol/util/sokol_gfx_imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
2372
3rd/sokol/util/sokol_gl.h
Normal file
2372
3rd/sokol/util/sokol_gl.h
Normal file
File diff suppressed because it is too large
Load Diff
1088
3rd/sokol/util/sokol_imgui.h
Normal file
1088
3rd/sokol/util/sokol_imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,9 @@
|
||||
#include "tkc/date_time.h"
|
||||
#include "tkc/mem.h"
|
||||
|
||||
#define SOKOL_IMPL
|
||||
#include "sokol/sokol_time.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
@ -83,10 +86,16 @@ static ret_t date_time_get_now_impl(date_time_t* dt) {
|
||||
#endif
|
||||
|
||||
uint64_t get_time_ms() {
|
||||
#if 0
|
||||
/*
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
return (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000;
|
||||
*/
|
||||
#else
|
||||
uint64_t now = stm_now();
|
||||
return now/1000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sleep_ms(uint32_t ms) {
|
||||
@ -102,6 +111,8 @@ static uint32_t s_heap_mem[1024 * 1024];
|
||||
#endif /*HAS_STD_MALLOC*/
|
||||
|
||||
ret_t platform_prepare(void) {
|
||||
stm_setup();
|
||||
|
||||
#ifndef HAS_STD_MALLOC
|
||||
tk_mem_init(s_heap_mem, sizeof(s_heap_mem));
|
||||
#endif /*HAS_STD_MALLOC*/
|
||||
|
Loading…
Reference in New Issue
Block a user