summaryrefslogtreecommitdiff
path: root/thirdparty/stb/tools
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /thirdparty/stb/tools
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'thirdparty/stb/tools')
-rw-r--r--thirdparty/stb/tools/README.footer.md121
-rw-r--r--thirdparty/stb/tools/README.header.md11
-rw-r--r--thirdparty/stb/tools/README.list20
-rw-r--r--thirdparty/stb/tools/easy_font_maker.c211
-rw-r--r--thirdparty/stb/tools/make_readme.c64
-rw-r--r--thirdparty/stb/tools/make_readme.dsp97
-rw-r--r--thirdparty/stb/tools/mr.bat1
-rw-r--r--thirdparty/stb/tools/unicode.c749
-rw-r--r--thirdparty/stb/tools/unicode/unicode.dsp88
9 files changed, 1362 insertions, 0 deletions
diff --git a/thirdparty/stb/tools/README.footer.md b/thirdparty/stb/tools/README.footer.md
new file mode 100644
index 0000000..f6f4bf5
--- /dev/null
+++ b/thirdparty/stb/tools/README.footer.md
@@ -0,0 +1,121 @@
+
+FAQ
+---
+
+#### What's the license?
+
+These libraries are in the public domain. You can do anything you
+want with them. You have no legal obligation
+to do anything else, although I appreciate attribution.
+
+They are also licensed under the MIT open source license, if you have lawyers
+who are unhappy with public domain. Every source file includes an explicit
+dual-license for you to choose from.
+
+#### <a name="other_libs"></a> Are there other single-file public-domain/open source libraries with minimal dependencies out there?
+
+[Yes.](https://github.com/nothings/single_file_libs)
+
+#### If I wrap an stb library in a new library, does the new library have to be public domain/MIT?
+
+No, because it's public domain you can freely relicense it to whatever license your new
+library wants to be.
+
+#### What's the deal with SSE support in GCC-based compilers?
+
+stb_image will either use SSE2 (if you compile with -msse2) or
+will not use any SIMD at all, rather than trying to detect the
+processor at runtime and handle it correctly. As I understand it,
+the approved path in GCC for runtime-detection require
+you to use multiple source files, one for each CPU configuration.
+Because stb_image is a header-file library that compiles in only
+one source file, there's no approved way to build both an
+SSE-enabled and a non-SSE-enabled variation.
+
+While we've tried to work around it, we've had multiple issues over
+the years due to specific versions of gcc breaking what we're doing,
+so we've given up on it. See https://github.com/nothings/stb/issues/280
+and https://github.com/nothings/stb/issues/410 for examples.
+
+#### Some of these libraries seem redundant to existing open source libraries. Are they better somehow?
+
+Generally they're only better in that they're easier to integrate,
+easier to use, and easier to release (single file; good API; no
+attribution requirement). They may be less featureful, slower,
+and/or use more memory. If you're already using an equivalent
+library, there's probably no good reason to switch.
+
+#### Can I link directly to the table of stb libraries?
+
+You can use [this URL](https://github.com/nothings/stb#stb_libs) to link directly to that list.
+
+#### Why do you list "lines of code"? It's a terrible metric.
+
+Just to give you some idea of the internal complexity of the library,
+to help you manage your expectations, or to let you know what you're
+getting into. While not all the libraries are written in the same
+style, they're certainly similar styles, and so comparisons between
+the libraries are probably still meaningful.
+
+Note though that the lines do include both the implementation, the
+part that corresponds to a header file, and the documentation.
+
+#### Why single-file headers?
+
+Windows doesn't have standard directories where libraries
+live. That makes deploying libraries in Windows a lot more
+painful than open source developers on Unix-derivates generally
+realize. (It also makes library dependencies a lot worse in Windows.)
+
+There's also a common problem in Windows where a library was built
+against a different version of the runtime library, which causes
+link conflicts and confusion. Shipping the libs as headers means
+you normally just compile them straight into your project without
+making libraries, thus sidestepping that problem.
+
+Making them a single file makes it very easy to just
+drop them into a project that needs them. (Of course you can
+still put them in a proper shared library tree if you want.)
+
+Why not two files, one a header and one an implementation?
+The difference between 10 files and 9 files is not a big deal,
+but the difference between 2 files and 1 file is a big deal.
+You don't need to zip or tar the files up, you don't have to
+remember to attach *two* files, etc.
+
+#### Why "stb"? Is this something to do with Set-Top Boxes?
+
+No, they are just the initials for my name, Sean T. Barrett.
+This was not chosen out of egomania, but as a moderately sane
+way of namespacing the filenames and source function names.
+
+#### Will you add more image types to stb_image.h?
+
+If people submit them, I generally add them, but the goal of stb_image
+is less for applications like image viewer apps (which need to support
+every type of image under the sun) and more for things like games which
+can choose what images to use, so I may decline to add them if they're
+too rare or if the size of implementation vs. apparent benefit is too low.
+
+#### Do you have any advice on how to create my own single-file library?
+
+Yes. https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
+
+#### Why public domain?
+
+I prefer it over GPL, LGPL, BSD, zlib, etc. for many reasons.
+Some of them are listed here:
+https://github.com/nothings/stb/blob/master/docs/why_public_domain.md
+
+#### Why C?
+
+Primarily, because I use C, not C++. But it does also make it easier
+for other people to use them from other languages.
+
+#### Why not C99? stdint.h, declare-anywhere, etc.
+
+I still use MSVC 6 (1998) as my IDE because it has better human factors
+for me than later versions of MSVC.
+
+
+
diff --git a/thirdparty/stb/tools/README.header.md b/thirdparty/stb/tools/README.header.md
new file mode 100644
index 0000000..41e55f1
--- /dev/null
+++ b/thirdparty/stb/tools/README.header.md
@@ -0,0 +1,11 @@
+stb
+===
+
+single-file public domain (or MIT licensed) libraries for C/C++ <a name="stb_libs"></a>
+
+Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
+by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
+
+
+library | lastest version | category | LoC | description
+--------------------- | ---- | -------- | --- | --------------------------------
diff --git a/thirdparty/stb/tools/README.list b/thirdparty/stb/tools/README.list
new file mode 100644
index 0000000..cc59037
--- /dev/null
+++ b/thirdparty/stb/tools/README.list
@@ -0,0 +1,20 @@
+stb_vorbis.c | audio | decode ogg vorbis files from file/memory to float/16-bit signed output
+stb_image.h | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
+stb_truetype.h | graphics | parse, decode, and rasterize characters from truetype fonts
+stb_image_write.h | graphics | image writing to disk: PNG, TGA, BMP
+stb_image_resize.h | graphics | resize images larger/smaller with good quality
+stb_rect_pack.h | graphics | simple 2D rectangle packer with decent quality
+stb_sprintf.h | utility | fast sprintf, snprintf for C/C++
+stretchy_buffer.h | utility | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++
+stb_textedit.h | user interface | guts of a text editor for games etc implementing them from scratch
+stb_voxel_render.h | 3D graphics | Minecraft-esque voxel rendering "engine" with many more features
+stb_dxt.h | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor
+stb_perlin.h | 3D graphics | revised Perlin noise (3D input, 1D output)
+stb_easy_font.h | 3D graphics | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
+stb_tilemap_editor.h | game dev | embeddable tilemap editor
+stb_herringbone_wang_tile.h | game dev | herringbone Wang tile map generator
+stb_c_lexer.h | parsing | simplify writing parsers for C-like languages
+stb_divide.h | math | more useful 32-bit modulus e.g. "euclidean divide"
+stb_connected_components.h | misc | incrementally compute reachability on grids
+stb.h | misc | helper functions for C, mostly redundant in C++; basically author's personal stuff
+stb_leakcheck.h | misc | quick-and-dirty malloc/free leak-checking
diff --git a/thirdparty/stb/tools/easy_font_maker.c b/thirdparty/stb/tools/easy_font_maker.c
new file mode 100644
index 0000000..f1b4836
--- /dev/null
+++ b/thirdparty/stb/tools/easy_font_maker.c
@@ -0,0 +1,211 @@
+// This program was used to encode the data for stb_simple_font.h
+
+#define STB_DEFINE
+#include "stb.h"
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"
+
+int w,h;
+uint8 *data;
+
+int last_x[2], last_y[2];
+int num_seg[2], non_empty;
+#if 0
+typedef struct
+{
+ unsigned short first_segment;
+ unsigned char advance;
+} chardata;
+
+typedef struct
+{
+ unsigned char x:4;
+ unsigned char y:4;
+ unsigned char len:3;
+ unsigned char dir:1;
+} segment;
+
+segment *segments;
+
+void add_seg(int x, int y, int len, int horizontal)
+{
+ segment s;
+ s.x = x;
+ s.y = y;
+ s.len = len;
+ s.dir = horizontal;
+ assert(s.x == x);
+ assert(s.y == y);
+ assert(s.len == len);
+ stb_arr_push(segments, s);
+}
+#else
+typedef struct
+{
+ unsigned char first_segment:8;
+ unsigned char first_v_segment:8;
+ unsigned char advance:5;
+ unsigned char voff:1;
+} chardata;
+
+#define X_LIMIT 1
+#define LEN_LIMIT 7
+
+typedef struct
+{
+ unsigned char dx:1;
+ unsigned char y:4;
+ unsigned char len:3;
+} segment;
+
+segment *segments;
+segment *vsegments;
+
+void add_seg(int x, int y, int len, int horizontal)
+{
+ segment s;
+
+ while (x - last_x[horizontal] > X_LIMIT) {
+ add_seg(last_x[horizontal] + X_LIMIT, 0, 0, horizontal);
+ }
+ while (len > LEN_LIMIT) {
+ add_seg(x, y, LEN_LIMIT, horizontal);
+ len -= LEN_LIMIT;
+ x += LEN_LIMIT*horizontal;
+ y += LEN_LIMIT*!horizontal;
+ }
+
+ s.dx = x - last_x[horizontal];
+ s.y = y;
+ s.len = len;
+ non_empty += len != 0;
+ //assert(s.x == x);
+ assert(s.y == y);
+ assert(s.len == len);
+ ++num_seg[horizontal];
+ if (horizontal)
+ stb_arr_push(segments, s);
+ else
+ stb_arr_push(vsegments, s);
+ last_x[horizontal] = x;
+}
+
+void print_segments(segment *s)
+{
+ int i, hpos;
+ printf(" ");
+ hpos = 4;
+ for (i=0; i < stb_arr_len(s); ++i) {
+ // repack for portability
+ unsigned char seg = s[i].len + s[i].dx*8 + s[i].y*16;
+ hpos += printf("%d,", seg);
+ if (hpos > 72 && i+1 < stb_arr_len(s)) {
+ hpos = 4;
+ printf("\n ");
+ }
+ }
+ printf("\n");
+}
+
+#endif
+
+chardata charinfo[128];
+
+int parse_char(int x, chardata *c, int offset)
+{
+ int start_x = x, end_x, top_y = 0, y;
+
+ c->first_segment = stb_arr_len(segments);
+ c->first_v_segment = stb_arr_len(vsegments) - offset;
+ assert(c->first_segment == stb_arr_len(segments));
+ assert(c->first_v_segment + offset == stb_arr_len(vsegments));
+
+ // find advance distance
+ end_x = x+1;
+ while (data[end_x*3] == 255)
+ ++end_x;
+ c->advance = end_x - start_x + 1;
+
+ last_x[0] = last_x[1] = 0;
+ last_y[0] = last_y[1] = 0;
+
+ for (y=2; y < h; ++y) {
+ for (x=start_x; x < end_x; ++x) {
+ if (data[y*3*w+x*3+1] < 255) {
+ top_y = y;
+ break;
+ }
+ }
+ if (top_y)
+ break;
+ }
+ c->voff = top_y > 2;
+ if (top_y > 2)
+ top_y = 3;
+
+ for (x=start_x; x < end_x; ++x) {
+ int y;
+ for (y=2; y < h; ++y) {
+ if (data[y*3*w+x*3+1] < 255) {
+ if (data[y*3*w+x*3+0] == 255) { // red
+ int len=0;
+ while (y+len < h && data[(y+len)*3*w+x*3+0] == 255 && data[(y+len)*3*w+x*3+1] == 0) {
+ data[(y+len)*3*w+x*3+0] = 0;
+ ++len;
+ }
+ add_seg(x-start_x,y-top_y,len,0);
+ }
+ if (data[y*3*w+x*3+2] == 255) { // blue
+ int len=0;
+ while (x+len < end_x && data[y*3*w+(x+len)*3+2] == 255 && data[y*3*w+(x+len)*3+1] == 0) {
+ data[y*3*w+(x+len)*3+2] = 0;
+ ++len;
+ }
+ add_seg(x-start_x,y-top_y,len,1);
+ }
+ }
+ }
+ }
+ return end_x;
+}
+
+
+int main(int argc, char **argv)
+{
+ int c, x=0;
+ data = stbi_load("easy_font_raw.png", &w, &h, 0, 3);
+ for (c=32; c < 127; ++c) {
+ x = parse_char(x, &charinfo[c], 0);
+ printf("%3d -- %3d %3d\n", c, charinfo[c].first_segment, charinfo[c].first_v_segment);
+ }
+ printf("===\n");
+ printf("%d %d %d\n", num_seg[0], num_seg[1], non_empty);
+ printf("%d\n", sizeof(segments[0]) * stb_arr_len(segments));
+ printf("%d\n", sizeof(segments[0]) * stb_arr_len(segments) + sizeof(segments[0]) * stb_arr_len(vsegments) + sizeof(charinfo[32])*95);
+
+ printf("struct {\n"
+ " unsigned char advance;\n"
+ " unsigned char h_seg;\n"
+ " unsigned char v_seg;\n"
+ "} stb_easy_font_charinfo[96] = {\n");
+ charinfo[c].first_segment = stb_arr_len(segments);
+ charinfo[c].first_v_segment = stb_arr_len(vsegments);
+ for (c=32; c < 128; ++c) {
+ if ((c & 3) == 0) printf(" ");
+ printf("{ %2d,%3d,%3d },",
+ charinfo[c].advance + 16*charinfo[c].voff,
+ charinfo[c].first_segment,
+ charinfo[c].first_v_segment);
+ if ((c & 3) == 3) printf("\n"); else printf(" ");
+ }
+ printf("};\n\n");
+
+ printf("unsigned char stb_easy_font_hseg[%d] = {\n", stb_arr_len(segments));
+ print_segments(segments);
+ printf("};\n\n");
+
+ printf("unsigned char stb_easy_font_vseg[%d] = {\n", stb_arr_len(vsegments));
+ print_segments(vsegments);
+ printf("};\n");
+ return 0;
+}
diff --git a/thirdparty/stb/tools/make_readme.c b/thirdparty/stb/tools/make_readme.c
new file mode 100644
index 0000000..b28c4ff
--- /dev/null
+++ b/thirdparty/stb/tools/make_readme.c
@@ -0,0 +1,64 @@
+#define STB_DEFINE
+#include "../stb.h"
+
+int main(int argc, char **argv)
+{
+ int i;
+ int hlen, flen, listlen, total_lines = 0;
+ char *header = stb_file("README.header.md", &hlen); // stb_file - read file into malloc()ed buffer
+ char *footer = stb_file("README.footer.md", &flen); // stb_file - read file into malloc()ed buffer
+ char **list = stb_stringfile("README.list", &listlen); // stb_stringfile - read file lines into malloced array of strings
+
+ FILE *f = fopen("../README.md", "wb");
+
+ fprintf(f, "<!--- THIS FILE IS AUTOMATICALLY GENERATED, DO NOT CHANGE IT BY HAND --->\n\n");
+ fwrite(header, 1, hlen, f);
+
+ for (i=0; i < listlen; ++i) {
+ int num,j;
+ char **tokens = stb_tokens_stripwhite(list[i], "|", &num); // stb_tokens -- tokenize string into malloced array of strings
+ int num_lines;
+ char **lines = stb_stringfile(stb_sprintf("../%s", tokens[0]), &num_lines);
+ char *s1, *s2,*s3;
+ s1 = strchr(lines[0], '-');
+ if (!s1) stb_fatal("Couldn't find '-' before version number in %s", tokens[0]); // stb_fatal -- print error message & exit
+ s2 = strchr(s1+2, '-');
+ if (!s2) stb_fatal("Couldn't find '-' after version number in %s", tokens[0]); // stb_fatal -- print error message & exit
+ *s2 = 0;
+ s1 += 1;
+ s1 = stb_trimwhite(s1); // stb_trimwhite -- advance pointer to after whitespace & delete trailing whitespace
+ if (*s1 == 'v') ++s1;
+ s3 = tokens[0];
+ stb_trimwhite(s3);
+ fprintf(f, "**[");
+ if (strlen(s3) < 21) {
+ fprintf(f, "%s", tokens[0]);
+ } else {
+ char buffer[256];
+ strncpy(buffer, s3, 18);
+ buffer[18] = 0;
+ strcat(buffer, "...");
+ fprintf(f, "%s", buffer);
+ }
+ fprintf(f, "](%s)**", tokens[0]);
+ fprintf(f, " | %s", s1);
+ s1 = stb_trimwhite(tokens[1]); // stb_trimwhite -- advance pointer to after whitespace & delete trailing whitespace
+ s2 = stb_dupreplace(s1, " ", "&nbsp;"); // stb_dupreplace -- search & replace string and malloc result
+ fprintf(f, " | %s", s2);
+ free(s2);
+ fprintf(f, " | %d", num_lines);
+ total_lines += num_lines;
+ for (j=2; j < num; ++j)
+ fprintf(f, " | %s", tokens[j]);
+ fprintf(f, "\n");
+ }
+
+ fprintf(f, "\n");
+ fprintf(f, "Total libraries: %d \n", listlen);
+ fprintf(f, "Total lines of C code: %d\n\n", total_lines);
+
+ fwrite(footer, 1, flen, f);
+ fclose(f);
+
+ return 0;
+}
diff --git a/thirdparty/stb/tools/make_readme.dsp b/thirdparty/stb/tools/make_readme.dsp
new file mode 100644
index 0000000..232dd86
--- /dev/null
+++ b/thirdparty/stb/tools/make_readme.dsp
@@ -0,0 +1,97 @@
+# Microsoft Developer Studio Project File - Name="make_readme" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=make_readme - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "make_readme.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "make_readme.mak" CFG="make_readme - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "make_readme - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "make_readme - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "make_readme - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "make_readme - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug\make_readme"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "make_readme - Win32 Release"
+# Name "make_readme - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\make_readme.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\README.header.md
+# End Source File
+# Begin Source File
+
+SOURCE=.\README.list
+# End Source File
+# End Target
+# End Project
diff --git a/thirdparty/stb/tools/mr.bat b/thirdparty/stb/tools/mr.bat
new file mode 100644
index 0000000..475bc4f
--- /dev/null
+++ b/thirdparty/stb/tools/mr.bat
@@ -0,0 +1 @@
+debug\make_readme
diff --git a/thirdparty/stb/tools/unicode.c b/thirdparty/stb/tools/unicode.c
new file mode 100644
index 0000000..8b9d8da
--- /dev/null
+++ b/thirdparty/stb/tools/unicode.c
@@ -0,0 +1,749 @@
+#define STB_DEFINE
+#include "../stb.h"
+
+// create unicode mappings
+//
+// Two kinds of mappings:
+// map to a number
+// map to a bit
+//
+// For mapping to a number, we use the following strategy:
+//
+// User supplies:
+// 1. a table of numbers (for now we use uint16, so full Unicode table is 4MB)
+// 2. a "don't care" value
+// 3. define a 'fallback' value (typically 0)
+// 4. define a fast-path range (typically 0..255 or 0..1023) [@TODO: automate detecting this]
+//
+// Code:
+// 1. Determine range of *end* of unicode codepoints (U+10FFFF and down) which
+// all have the same value (or don't care). If large enough, emit this as a
+// special case in the code.
+// 2. Repeat above, limited to at most U+FFFF.
+// 3. Cluster the data into intervals of 8,16,32,64,128,256 numeric values.
+// 3a. If all the values in an interval are fallback/dont-care, no further processing
+// 3b. Find the "trimmed range" outside which all the values are the fallback or don't care
+// 3c. Find the "special trimmed range" outside which all the values are some constant or don't care
+// 4. Pack the clusters into continuous memory, and find previous instances of
+// the cluster. Repeat for trimmed & special-trimmed. In the first case, find
+// previous instances of the cluster (allow don't-care to match in either
+// direction), both aligned and mis-aligned; in the latter, starting where
+// things start or mis-aligned. Build an index table specifiying the
+// location of each cluster (and its length). Allow an extra indirection here;
+// the full-sized index can index a smaller table which has the actual offset
+// (and lengths).
+// 5. Associate with each packed continuous memory above the amount of memory
+// required to store the data w/ smallest datatype (of uint8, uint16, uint32).
+// Discard the continuous memory. Recurse on each index table, but avoid the
+// smaller packing.
+//
+// For mapping to a bit, we pack the results for 8 characters into a byte, and then apply
+// the above strategy. Note that there may be more optimal approaches with e.g. packing
+// 8 different bits into a single structure, though, which we should explore eventually.
+
+
+// currently we limit *indices* to being 2^16, and we pack them as
+// index + end_trim*2^16 + start_trim*2^24; specials have to go in a separate table
+typedef uint32 uval;
+#define UVAL_DONT_CARE_DEFAULT 0xffffffff
+
+typedef struct
+{
+ uval *input;
+ uint32 dont_care;
+ uint32 fallback;
+ int fastpath;
+ int length;
+ int depth;
+ int has_sign;
+ int splittable;
+ int replace_fallback_with_codepoint;
+ size_t input_size;
+ size_t inherited_storage;
+} table;
+
+typedef struct
+{
+ int split_log2;
+ table result; // index into not-returned table
+ int storage;
+} output;
+
+typedef struct
+{
+ table t;
+ char **output_name;
+} info;
+
+typedef struct
+{
+ size_t path;
+ size_t size;
+} result;
+
+typedef struct
+{
+ uint8 trim_end;
+ uint8 trim_start;
+ uint8 special;
+ uint8 aligned;
+ uint8 indirect;
+
+ uint16 overhead; // add some forced overhead for each mode to avoid getting complex encoding when it doesn't save much
+
+} mode_info;
+
+mode_info modes[] =
+{
+ { 0,0,0,0,0, 32, },
+ { 0,0,0,0,1, 100, },
+ { 0,0,0,1,0, 32, },
+ { 0,0,0,1,1, 100, },
+ { 0,0,1,0,1, 100, },
+ { 0,0,1,1,0, 32, },
+ { 0,0,1,1,1, 200, },
+ { 1,0,0,0,0, 100, },
+ { 1,0,0,0,1, 120, },
+ { 1,1,0,0,0, 100, },
+ { 1,1,0,0,1, 130, },
+ { 1,0,1,0,0, 130, },
+ { 1,0,1,0,1, 180, },
+ { 1,1,1,0,0, 180, },
+ { 1,1,1,0,1, 200, },
+};
+
+#define MODECOUNT (sizeof(modes)/sizeof(modes[0]))
+#define CLUSTERSIZECOUNT 6 // 8,16, 32,64, 128,256
+
+size_t size_for_max_number(uint32 number)
+{
+ if (number == 0) return 0;
+ if (number < 256) return 1;
+ if (number < 256*256) return 2;
+ if (number < 256*256*256) return 3;
+ return 4;
+}
+
+size_t size_for_max_number_aligned(uint32 number)
+{
+ size_t n = size_for_max_number(number);
+ return n == 3 ? 4 : n;
+}
+
+uval get_data(uval *data, int offset, uval *end)
+{
+ if (data + offset >= end)
+ return 0;
+ else
+ return data[offset];
+}
+
+int safe_len(uval *data, int len, uval *end)
+{
+ if (len > end - data)
+ return end - data;
+ return len;
+}
+
+uval tempdata[256];
+int dirty=0;
+
+size_t find_packed(uval **packed, uval *data, int len, int aligned, int fastpath, uval *end, int offset, int replace)
+{
+ int packlen = stb_arr_len(*packed);
+ int i,p;
+
+ if (data+len > end || replace) {
+ int safelen = safe_len(data, len, end);
+ memset(tempdata, 0, dirty*sizeof(tempdata[0]));
+ memcpy(tempdata, data, safelen * sizeof(data[0]));
+ data = tempdata;
+ dirty = len;
+ }
+ if (replace) {
+ int i;
+ int safelen = safe_len(data, len, end);
+ for (i=0; i < safelen; ++i)
+ if (data[i] == 0)
+ data[i] = offset+i;
+ }
+
+ if (len <= 0)
+ return 0;
+ if (!fastpath) {
+ if (aligned) {
+ for (i=0; i < packlen; i += len)
+ if ((*packed)[i] == data[0] && 0==memcmp(&(*packed)[i], data, len * sizeof(uval)))
+ return i / len;
+ } else {
+ for (i=0; i < packlen-len+1; i += 1 )
+ if ((*packed)[i] == data[0] && 0==memcmp(&(*packed)[i], data, len * sizeof(uval)))
+ return i;
+ }
+ }
+ p = stb_arr_len(*packed);
+ for (i=0; i < len; ++i)
+ stb_arr_push(*packed, data[i]);
+ return p;
+}
+
+void output_table(char *name1, char *name2, uval *data, int length, int sign, char **names)
+{
+ char temp[20];
+ uval maxv = 0;
+ int bytes, numlen, at_newline;
+ int linelen = 79; // @TODO: make table more readable by choosing a length that's a multiple?
+ int i,pos, do_split=0;
+ for (i=0; i < length; ++i)
+ if (sign)
+ maxv = stb_max(maxv, (uval)abs((int)data[i]));
+ else
+ maxv = stb_max(maxv, data[i]);
+ bytes = size_for_max_number_aligned(maxv);
+ sprintf(temp, "%d", maxv);
+ numlen=strlen(temp);
+ if (sign)
+ ++numlen;
+
+ if (bytes == 0)
+ return;
+
+ printf("uint%d %s%s[%d] = {\n", bytes*8, name1, name2, length);
+ at_newline = 1;
+ for (i=0; i < length; ++i) {
+ if (pos + numlen + 2 > linelen) {
+ printf("\n");
+ at_newline = 1;
+ pos = 0;
+ }
+ if (at_newline) {
+ printf(" ");
+ pos = 2;
+ at_newline = 0;
+ } else {
+ printf(" ");
+ ++pos;
+ }
+ printf("%*d,", numlen, data[i]);
+ pos += numlen+1;
+ }
+ if (!at_newline) printf("\n");
+ printf("};\n");
+}
+
+void output_table_with_trims(char *name1, char *name2, uval *data, int length)
+{
+ uval maxt=0, maxp=0;
+ int i,d,s,e, count;
+ // split the table into two pieces
+ uval *trims = NULL;
+
+ if (length == 0)
+ return;
+
+ for (i=0; i < stb_arr_len(data); ++i) {
+ stb_arr_push(trims, data[i] >> 16);
+ data[i] &= 0xffff;
+ maxt = stb_max(maxt, trims[i]);
+ maxp = stb_max(maxp, data[i]);
+ }
+
+ d=s=e=1;
+ if (maxt >= 256) {
+ // need to output start & end values
+ if (maxp >= 256) {
+ // can pack into a single table
+ printf("struct { uint16 val; uint8 start, end; } %s%s[%d] = {\n", name1, name2, length);
+ } else {
+ output_table(name1, name2, data, length, 0, 0);
+ d=0;
+ printf("struct { uint8 start, end; } %s%s_trim[%d] = {\n", name1, name2, length);
+ }
+ } else if (maxt > 0) {
+ if (maxp >= 256) {
+ output_table(name1, name2, data, length, 0, 0);
+ output_table(name1, stb_sprintf("%s_end", name2), trims, length, 0, 0);
+ return;
+ } else {
+ printf("struct { uint8 val, end; } %s%s[%d] = {\n", name1, name2, length);
+ s=0;
+ }
+ } else {
+ output_table(name1, name2, data, length, 0, 0);
+ return;
+ }
+ // d or s can be zero (but not both), e is always present and last
+ count = d + s + e;
+ assert(count >= 2 && count <= 3);
+
+ {
+ char temp[60];
+ uval maxv = 0;
+ int numlen, at_newline, len;
+ int linelen = 79; // @TODO: make table more readable by choosing a length that's a multiple?
+ int i,pos, do_split=0;
+ numlen = 0;
+ for (i=0; i < length; ++i) {
+ if (count == 2)
+ sprintf(temp, "{%d,%d}", d ? data[i] : (trims[i]>>8), trims[i]&255);
+ else
+ sprintf(temp, "{%d,%d,%d}", data[i], trims[i]>>8, trims[i]&255);
+ len = strlen(temp);
+ numlen = stb_max(len, numlen);
+ }
+
+ at_newline = 1;
+ for (i=0; i < length; ++i) {
+ if (pos + numlen + 2 > linelen) {
+ printf("\n");
+ at_newline = 1;
+ pos = 0;
+ }
+ if (at_newline) {
+ printf(" ");
+ pos = 2;
+ at_newline = 0;
+ } else {
+ printf(" ");
+ ++pos;
+ }
+ if (count == 2)
+ sprintf(temp, "{%d,%d}", d ? data[i] : (trims[i]>>8), trims[i]&255);
+ else
+ sprintf(temp, "{%d,%d,%d}", data[i], trims[i]>>8, trims[i]&255);
+ printf("%*s,", numlen, temp);
+ pos += numlen+1;
+ }
+ if (!at_newline) printf("\n");
+ printf("};\n");
+ }
+}
+
+int weight=1;
+
+table pack_for_mode(table *t, int mode, char *table_name)
+{
+ size_t extra_size;
+ int i;
+ uval maxv;
+ mode_info mi = modes[mode % MODECOUNT];
+ int size = 8 << (mode / MODECOUNT);
+ table newtab;
+ uval *packed = NULL;
+ uval *index = NULL;
+ uval *indirect = NULL;
+ uval *specials = NULL;
+ newtab.dont_care = UVAL_DONT_CARE_DEFAULT;
+ if (table_name)
+ printf("// clusters of %d\n", size);
+ for (i=0; i < t->length; i += size) {
+ uval newval;
+ int fastpath = (i < t->fastpath);
+ if (mi.special) {
+ int end_trim = size-1;
+ int start_trim = 0;
+ uval special;
+ // @TODO: pick special from start or end instead of only end depending on which is longer
+ for(;;) {
+ special = t->input[i + end_trim];
+ if (special != t->dont_care || end_trim == 0)
+ break;
+ --end_trim;
+ }
+ // at this point, special==inp[end_trim], and end_trim >= 0
+ if (special == t->dont_care && !fastpath) {
+ // entire block is don't care, so OUTPUT don't care
+ stb_arr_push(index, newtab.dont_care);
+ continue;
+ } else {
+ uval pos, trim;
+ if (mi.trim_end && !fastpath) {
+ while (end_trim >= 0) {
+ if (t->input[i + end_trim] == special || t->input[i + end_trim] == t->dont_care)
+ --end_trim;
+ else
+ break;
+ }
+ }
+
+ if (mi.trim_start && !fastpath) {
+ while (start_trim < end_trim) {
+ if (t->input[i + start_trim] == special || t->input[i + start_trim] == t->dont_care)
+ ++start_trim;
+ else
+ break;
+ }
+ }
+
+ // end_trim points to the last character we have to output
+
+ // find the first match, or add it
+ pos = find_packed(&packed, &t->input[i+start_trim], end_trim-start_trim+1, mi.aligned, fastpath, &t->input[t->length], i+start_trim, t->replace_fallback_with_codepoint);
+
+ // encode as a uval
+ if (!mi.trim_end) {
+ if (end_trim == 0)
+ pos = special;
+ else
+ pos = pos | 0x80000000;
+ } else {
+ assert(end_trim < size && end_trim >= -1);
+ if (!fastpath) assert(end_trim < size-1); // special always matches last one
+ assert(end_trim < size && end_trim+1 >= 0);
+ if (!fastpath) assert(end_trim+1 < size);
+
+ if (mi.trim_start)
+ trim = start_trim*256 + (end_trim+1);
+ else
+ trim = end_trim+1;
+
+ assert(pos < 65536); // @TODO: if this triggers, just bail on this search path
+ pos = pos + (trim << 16);
+ }
+
+ newval = pos;
+
+ stb_arr_push(specials, special);
+ }
+ } else if (mi.trim_end) {
+ int end_trim = size-1;
+ int start_trim = 0;
+ uval pos, trim;
+
+ while (end_trim >= 0 && !fastpath)
+ if (t->input[i + end_trim] == t->fallback || t->input[i + end_trim] == t->dont_care)
+ --end_trim;
+ else
+ break;
+
+ if (mi.trim_start && !fastpath) {
+ while (start_trim < end_trim) {
+ if (t->input[i + start_trim] == t->fallback || t->input[i + start_trim] == t->dont_care)
+ ++start_trim;
+ else
+ break;
+ }
+ }
+
+ // end_trim points to the last character we have to output, and can be -1
+ ++end_trim; // make exclusive at end
+
+ if (end_trim == 0 && size == 256)
+ start_trim = end_trim = 1; // we can't make encode a length from 0..256 in 8 bits, so restrict end_trim to 1..256
+
+ // find the first match, or add it
+ pos = find_packed(&packed, &t->input[i+start_trim], end_trim - start_trim, mi.aligned, fastpath, &t->input[t->length], i+start_trim, t->replace_fallback_with_codepoint);
+
+ assert(end_trim <= size && end_trim >= 0);
+ if (size == 256)
+ assert(end_trim-1 < 256 && end_trim-1 >= 0);
+ else
+ assert(end_trim < 256 && end_trim >= 0);
+ if (size == 256)
+ --end_trim;
+
+ if (mi.trim_start)
+ trim = start_trim*256 + end_trim;
+ else
+ trim = end_trim;
+
+ assert(pos < 65536); // @TODO: if this triggers, just bail on this search path
+ pos = pos + (trim << 16);
+
+ newval = pos;
+ } else {
+ newval = find_packed(&packed, &t->input[i], size, mi.aligned, fastpath, &t->input[t->length], i, t->replace_fallback_with_codepoint);
+ }
+
+ if (mi.indirect) {
+ int j;
+ for (j=0; j < stb_arr_len(indirect); ++j)
+ if (indirect[j] == newval)
+ break;
+ if (j == stb_arr_len(indirect))
+ stb_arr_push(indirect, newval);
+ stb_arr_push(index, j);
+ } else {
+ stb_arr_push(index, newval);
+ }
+ }
+
+ // total up the new size for everything but the index table
+ extra_size = mi.overhead * weight; // not the actual overhead cost; a penalty to avoid excessive complexity
+ extra_size += 150; // per indirection
+ if (table_name)
+ extra_size = 0;
+
+ if (t->has_sign) {
+ // 'packed' contains two values, which should be packed positive & negative for size
+ uval maxv2;
+ for (i=0; i < stb_arr_len(packed); ++i)
+ if (packed[i] & 0x80000000)
+ maxv2 = stb_max(maxv2, packed[i]);
+ else
+ maxv = stb_max(maxv, packed[i]);
+ maxv = stb_max(maxv, maxv2) << 1;
+ } else {
+ maxv = 0;
+ for (i=0; i < stb_arr_len(packed); ++i)
+ if (packed[i] > maxv && packed[i] != t->dont_care)
+ maxv = packed[i];
+ }
+ extra_size += stb_arr_len(packed) * (t->splittable ? size_for_max_number(maxv) : size_for_max_number_aligned(maxv));
+ if (table_name) {
+ if (t->splittable)
+ output_table_with_trims(table_name, "", packed, stb_arr_len(packed));
+ else
+ output_table(table_name, "", packed, stb_arr_len(packed), t->has_sign, NULL);
+ }
+
+ maxv = 0;
+ for (i=0; i < stb_arr_len(specials); ++i)
+ if (specials[i] > maxv)
+ maxv = specials[i];
+ extra_size += stb_arr_len(specials) * size_for_max_number_aligned(maxv);
+ if (table_name)
+ output_table(table_name, "_default", specials, stb_arr_len(specials), 0, NULL);
+
+ maxv = 0;
+ for (i=0; i < stb_arr_len(indirect); ++i)
+ if (indirect[i] > maxv)
+ maxv = indirect[i];
+ extra_size += stb_arr_len(indirect) * size_for_max_number(maxv);
+
+ if (table_name && stb_arr_len(indirect)) {
+ if (mi.trim_end)
+ output_table_with_trims(table_name, "_index", indirect, stb_arr_len(indirect));
+ else {
+ assert(0); // this case should only trigger in very extreme circumstances
+ output_table(table_name, "_index", indirect, stb_arr_len(indirect), 0, NULL);
+ }
+ mi.trim_end = mi.special = 0;
+ }
+
+ if (table_name)
+ printf("// above tables should be %d bytes\n", extra_size);
+
+ maxv = 0;
+ for (i=0; i < stb_arr_len(index); ++i)
+ if (index[i] > maxv && index[i] != t->dont_care)
+ maxv = index[i];
+ newtab.splittable = mi.trim_end;
+ newtab.input_size = newtab.splittable ? size_for_max_number(maxv) : size_for_max_number_aligned(maxv);
+ newtab.input = index;
+ newtab.length = stb_arr_len(index);
+ newtab.inherited_storage = t->inherited_storage + extra_size;
+ newtab.fastpath = 0;
+ newtab.depth = t->depth+1;
+ stb_arr_free(indirect);
+ stb_arr_free(packed);
+ stb_arr_free(specials);
+
+ return newtab;
+}
+
+result pack_table(table *t, size_t path, int min_storage)
+{
+ int i;
+ result best;
+ best.size = t->inherited_storage + t->input_size * t->length;
+ best.path = path;
+
+ if ((int) t->inherited_storage > min_storage) {
+ best.size = stb_max(best.size, t->inherited_storage);
+ return best;
+ }
+
+ if (t->length <= 256 || t->depth >= 4) {
+ //printf("%08x: %7d\n", best.path, best.size);
+ return best;
+ }
+
+ path <<= 7;
+ for (i=0; i < MODECOUNT * CLUSTERSIZECOUNT; ++i) {
+ table newtab;
+ result r;
+ newtab = pack_for_mode(t, i, 0);
+ r = pack_table(&newtab, path+i+1, min_storage);
+ if (r.size < best.size)
+ best = r;
+ stb_arr_free(newtab.input);
+ //printf("Size: %6d + %6d\n", newtab.inherited_storage, newtab.input_size * newtab.length);
+ }
+ return best;
+}
+
+int pack_table_by_modes(table *t, int *modes)
+{
+ table s = *t;
+ while (*modes > -1) {
+ table newtab;
+ newtab = pack_for_mode(&s, *modes, 0);
+ if (s.input != t->input)
+ stb_arr_free(s.input);
+ s = newtab;
+ ++modes;
+ }
+ return s.inherited_storage + s.input_size * s.length;
+}
+
+int strip_table(table *t, int exceptions)
+{
+ uval terminal_value;
+ int p = t->length-1;
+ while (t->input[p] == t->dont_care)
+ --p;
+ terminal_value = t->input[p];
+
+ while (p >= 0x10000) {
+ if (t->input[p] != terminal_value && t->input[p] != t->dont_care) {
+ if (exceptions)
+ --exceptions;
+ else
+ break;
+ }
+ --p;
+ }
+ return p+1; // p is a character we must output
+}
+
+void optimize_table(table *t, char *table_name)
+{
+ int modelist[3] = { 85, -1 };
+ int modes[8];
+ int num_modes = 0;
+ int decent_size;
+ result r;
+ size_t path;
+ table s;
+
+ // strip tail end of table
+ int orig_length = t->length;
+ int threshhold = 0xffff;
+ int p = strip_table(t, 2);
+ int len_saved = t->length - p;
+ if (len_saved >= threshhold) {
+ t->length = p;
+ while (p > 0x10000) {
+ p = strip_table(t, 0);
+ len_saved = t->length - p;
+ if (len_saved < 0x10000)
+ break;
+ len_saved = orig_length - p;
+ if (len_saved < threshhold)
+ break;
+ threshhold *= 2;
+ }
+ }
+
+ t->depth = 1;
+
+
+ // find size of table if we use path 86
+ decent_size = pack_table_by_modes(t, modelist);
+
+
+ #if 1
+ // find best packing of remainder of table by exploring tree of packings
+ r = pack_table(t, 0, decent_size);
+ // use the computed 'path' to evaluate and output tree
+ path = r.path;
+ #else
+ path = 86;//90;//132097;
+ #endif
+
+ while (path) {
+ modes[num_modes++] = (path & 127) - 1;
+ path >>= 7;
+ }
+
+ printf("// modes: %d\n", r.path);
+ s = *t;
+ while (num_modes > 0) {
+ char name[256];
+ sprintf(name, "%s_%d", table_name, num_modes+1);
+ --num_modes;
+ s = pack_for_mode(&s, modes[num_modes], name);
+ }
+ // output the final table as-is
+ if (s.splittable)
+ output_table_with_trims(table_name, "_1", s.input, s.length);
+ else
+ output_table(table_name, "_1", s.input, s.length, 0, NULL);
+}
+
+uval unicode_table[0x110000];
+
+typedef struct
+{
+ uval lo,hi;
+} char_range;
+
+char_range get_range(char *str)
+{
+ char_range cr;
+ char *p;
+ cr.lo = strtol(str, &p, 16);
+ p = stb_skipwhite(p);
+ if (*p == '.')
+ cr.hi = strtol(p+2, NULL, 16);
+ else
+ cr.hi = cr.lo;
+ return cr;
+}
+
+char *skip_semi(char *s, int count)
+{
+ while (count) {
+ s = strchr(s, ';');
+ assert(s != NULL);
+ ++s;
+ --count;
+ }
+ return s;
+}
+
+int main(int argc, char **argv)
+{
+ table t;
+ uval maxv=0;
+ int i,n=0;
+ char **s = stb_stringfile("../../data/UnicodeData.txt", &n);
+ assert(s);
+ for (i=0; i < n; ++i) {
+ if (s[i][0] == '#' || s[i][0] == '\n' || s[i][0] == 0)
+ ;
+ else {
+ char_range cr = get_range(s[i]);
+ char *t = skip_semi(s[i], 13);
+ uval j, v;
+ if (*t == ';' || *t == '\n' || *t == 0)
+ v = 0;
+ else {
+ v = strtol(t, NULL, 16);
+ if (v < 65536) {
+ maxv = stb_max(v, maxv);
+ for (j=cr.lo; j <= cr.hi; ++j) {
+ unicode_table[j] = v;
+ //printf("%06x => %06x\n", j, v);
+ }
+ }
+ }
+ }
+ }
+
+ t.depth = 0;
+ t.dont_care = UVAL_DONT_CARE_DEFAULT;
+ t.fallback = 0;
+ t.fastpath = 256;
+ t.inherited_storage = 0;
+ t.has_sign = 0;
+ t.splittable = 0;
+ t.input = unicode_table;
+ t.input_size = size_for_max_number(maxv);
+ t.length = 0x110000;
+ t.replace_fallback_with_codepoint = 1;
+
+ optimize_table(&t, "stbu_upppercase");
+ return 0;
+}
diff --git a/thirdparty/stb/tools/unicode/unicode.dsp b/thirdparty/stb/tools/unicode/unicode.dsp
new file mode 100644
index 0000000..78e6a5b
--- /dev/null
+++ b/thirdparty/stb/tools/unicode/unicode.dsp
@@ -0,0 +1,88 @@
+# Microsoft Developer Studio Project File - Name="unicode" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=unicode - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "unicode.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "unicode.mak" CFG="unicode - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "unicode - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "unicode - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "unicode - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "unicode - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "unicode - Win32 Release"
+# Name "unicode - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\unicode.c
+# End Source File
+# End Target
+# End Project