From 529d8163b236e526dccb8640727a71b438febc8f Mon Sep 17 00:00:00 2001 From: Emmanuel Julien Date: Tue, 13 Jan 2015 17:43:14 +0100 Subject: [PATCH 001/522] Add support for writing through callback functions in stb_image_write.h. --- stb_image_write.h | 211 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 166 insertions(+), 45 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index da3f7e2..364932f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -19,16 +19,23 @@ ABOUT: The PNG output is not optimal; it is 20-50% larger than the file written by a decent optimizing implementation. This library is designed - for source code compactness and simplicitly, not optimal image file size + for source code compactness and simplicity, not optimal image file size or run-time performance. USAGE: - There are three functions, one for each image file format: + There are functions for each image file format and output method: - int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); - int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); - int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_png_to_file(char const *filename, int x, int y, int comp, const void *data, int stride_bytes); + int stbi_write_bmp_to_file(char const *filename, int x, int y, int comp, const void *data); + int stbi_write_tga_to_file(char const *filename, int x, int y, int comp, const void *data); + + int stbi_write_png_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data, int stride_bytes); + int stbi_write_bmp_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data); + int stbi_write_tga_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data); + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions. Each function returns 0 on failure and non-0 on success. @@ -51,6 +58,16 @@ USAGE: formats do not. (Thus you cannot write a native-format BMP through the BMP writer, both because it is in BGR order and because it may have padding at the end of the line.) + + =========================================================================== + + I/O callbacks + + I/O callbacks allow you to write to arbitrary sources, like packaged + files or some other source. + + The function you must define is "write" (writes some bytes of data). + */ #ifndef INCLUDE_STB_IMAGE_WRITE_H @@ -60,9 +77,22 @@ USAGE: extern "C" { #endif -extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); -extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); -extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +typedef struct +{ + int (*write) (void *user,void *data,int size); // write 'size' bytes from 'data'. return number of bytes actually written +} stbi_io_write_callbacks; + +extern int stbi_write_png_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data, int stride_bytes); +extern int stbi_write_bmp_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data); +extern int stbi_write_tga_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data); + +#ifndef STBI_WRITE_NO_STDIO + +extern int stbi_write_png_to_file(char const *filename, int x, int y, int comp, const void *data, int stride_bytes); +extern int stbi_write_bmp_to_file(char const *filename, int x, int y, int comp, const void *data); +extern int stbi_write_tga_to_file(char const *filename, int x, int y, int comp, const void *data); + +#endif // !STBI_WRITE_NO_STDIO #ifdef __cplusplus } @@ -72,28 +102,68 @@ extern int stbi_write_tga(char const *filename, int w, int h, int comp, const vo #ifdef STB_IMAGE_WRITE_IMPLEMENTATION +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO #include #include -#include #include #include +typedef struct +{ + stbi_io_write_callbacks io; + void *io_user_data; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_io_write_callbacks const *c, void *user) +{ + s->io = *c; + s->io_user_data = user; +} + +#ifndef STBI_WRITE_NO_STDIO + +static int stbi__stdio_write(void *user, void *data, int size) +{ + return (int) fwrite(data,1,size,(FILE*) user); +} + +static stbi_io_write_callbacks stbi__stdio_write_callbacks = +{ + stbi__stdio_write +}; + +static void stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = fopen(filename, "wb"); + stbi__start_write_callbacks(s, &stbi__stdio_write_callbacks, (void *) f); +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->io_user_data); +} + +#endif // !STBI_WRITE_NO_STDIO + typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; -static void writefv(FILE *f, const char *fmt, va_list v) +static void writefv(stbi__write_context const *s, const char *fmt, va_list v) { while (*fmt) { switch (*fmt++) { case ' ': break; - case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; } + case '1': { unsigned char x = (unsigned char) va_arg(v, int); s->io.write(s->io_user_data,&x,1); break; } case '2': { int x = va_arg(v,int); unsigned char b[2]; b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8); - fwrite(b,2,1,f); break; } + s->io.write(s->io_user_data,b,2); break; } case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4]; b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8); b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24); - fwrite(b,4,1,f); break; } + s->io.write(s->io_user_data,b,4); break; } default: assert(0); return; @@ -101,14 +171,14 @@ static void writefv(FILE *f, const char *fmt, va_list v) } } -static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c) +static void write3(stbi__write_context const *s, unsigned char a, unsigned char b, unsigned char c) { unsigned char arr[3]; arr[0] = a, arr[1] = b, arr[2] = c; - fwrite(arr, 3, 1, f); + s->io.write(s->io_user_data, arr, 3); } -static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad) +static void write_pixels(stbi__write_context const *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad) { unsigned char bg[3] = { 255, 0, 255}, px[3]; stbiw_uint32 zero = 0; @@ -126,65 +196,100 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, for (i=0; i < x; ++i) { unsigned char *d = (unsigned char *) data + (j*x+i)*comp; if (write_alpha < 0) - fwrite(&d[comp-1], 1, 1, f); + s->io.write(s->io_user_data, &d[comp-1], 1); switch (comp) { case 1: - case 2: fwrite(d, 1, 1, f); + case 2: s->io.write(s->io_user_data, d, 1); break; case 4: if (!write_alpha) { // composite against pink background for (k=0; k < 3; ++k) px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; - write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]); + write3(s, px[1-rgb_dir],px[1],px[1+rgb_dir]); break; } /* FALLTHROUGH */ case 3: - write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]); + write3(s, d[1-rgb_dir],d[1],d[1+rgb_dir]); break; } if (write_alpha > 0) - fwrite(&d[comp-1], 1, 1, f); + s->io.write(s->io_user_data, &d[comp-1], 1); } - fwrite(&zero,scanline_pad,1,f); + s->io.write(s->io_user_data,&zero,scanline_pad); } } -static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...) +static int outfile(stbi__write_context const *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...) { - FILE *f; if (y < 0 || x < 0) return 0; - f = fopen(filename, "wb"); - if (f) { - va_list v; - va_start(v, fmt); - writefv(f, fmt, v); - va_end(v); - write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad); - fclose(f); - } - return f != NULL; + va_list v; + va_start(v, fmt); + writefv(s, fmt, v); + va_end(v); + write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad); + return 1; } -int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +int stbi_write_bmp(stbi__write_context const *s, int x, int y, int comp, const void *data) { int pad = (-x*3) & 3; - return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad, + return outfile(s,-1,-1,x,y,comp,(void *) data,0,pad, "11 4 22 4" "4 44 22 444444", 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } -int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +int stbi_write_bmp_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, clbk, user); + return stbi_write_bmp(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO + +int stbi_write_bmp_to_file(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_file(&s,filename); + int r = stbi_write_bmp(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; +} + +#endif //!STBI_WRITE_NO_STDIO + +int stbi_write_tga(stbi__write_context const *s, int x, int y, int comp, const void *data) { int has_alpha = (comp == 2 || comp == 4); int colorbytes = has_alpha ? comp-1 : comp; int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 - return outfile(filename, -1,-1, x, y, comp, (void *) data, has_alpha, 0, + return outfile(s, -1,-1, x, y, comp, (void *) data, has_alpha, 0, "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8); } +int stbi_write_tga_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, clbk, user); + return stbi_write_tga(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO + +int stbi_write_tga_to_file(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s; + stbi__start_write_file(&s,filename); + int r = stbi_write_tga(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; +} + +#endif //!STBI_WRITE_NO_STDIO + // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() #define stbiw__sbraw(a) ((int *) (a) - 2) #define stbiw__sbm(a) stbiw__sbraw(a)[0] @@ -490,19 +595,35 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in return out; } -int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +int stbi_write_png(stbi__write_context const *s, int x, int y, int comp, const void *data, int stride_bytes) { - FILE *f; int len; unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (!png) return 0; - f = fopen(filename, "wb"); - if (!f) { free(png); return 0; } - fwrite(png, 1, len, f); - fclose(f); + int r = s->io.write(s->io_user_data, png, len); free(png); - return 1; + return r; } + +int stbi_write_png_to_callbacks(stbi_io_write_callbacks const *clbk, void *user, int x, int y, int comp, const void *data, int stride_bytes) +{ + stbi__write_context s; + stbi__start_write_callbacks(&s, clbk, user); + return stbi_write_png(&s, x, y, comp, data, stride_bytes); +} + +#ifndef STBI_WRITE_NO_STDIO + +int stbi_write_png_to_file(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + stbi__write_context s; + stbi__start_write_file(&s,filename); + int r = stbi_write_png(&s, x, y, comp, data, stride_bytes); + stbi__end_write_file(&s); + return r; +} +#endif //!STBI_WRITE_NO_STDIO + #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history From b3653cc3f17a02fe249671624d950d716a4b0806 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 18 Jan 2015 21:17:49 +0100 Subject: [PATCH 002/522] fix double free (found by cppcheck) --- stb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb.h b/stb.h index 4460516..bbd9379 100644 --- a/stb.h +++ b/stb.h @@ -10052,7 +10052,7 @@ char *stb_decompress_fromfile(char *filename, unsigned int *len) if (p == NULL) return NULL; if (p[0] != 0x57 || p[1] != 0xBc || p[2] || p[3]) { free(p); return NULL; } q = (char *) malloc(stb_decompress_length(p)+1); - if (!q) { free(p); free(p); return NULL; } + if (!q) { free(p); return NULL; } *len = stb_decompress((unsigned char *) q, p, n); if (*len) q[*len] = 0; free(p); From 347e7838be93e60aecb319cea83d3e15f2abef75 Mon Sep 17 00:00:00 2001 From: Guillaume Chereau Date: Mon, 20 Apr 2015 22:59:24 +0800 Subject: [PATCH 003/522] fix compilation of stb_image_write.h with gcc -O3 When compiling with -O3, gcc would complain that 'linear' might not be initialized if comp is superior to 4. In fact passing a value > 4 is an error anyway, but gcc does not know that. I changed the switch case to support comp > 4. I don't think it should affect the performances. --- stb_image_write.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 1048970..46f60b9 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -294,8 +294,8 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra linear[1] = scanline[x*comp + 1]; linear[0] = scanline[x*comp + 0]; break; - case 2: /* fallthrough */ - case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; + default: + linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; break; } stbiw__linear_to_rgbe(rgbe, linear); @@ -311,8 +311,8 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra linear[1] = scanline[x*comp + 1]; linear[0] = scanline[x*comp + 0]; break; - case 2: /* fallthrough */ - case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; + default: + linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; break; } stbiw__linear_to_rgbe(rgbe, linear); From d1d5f4ca96c09b0b2dca82247fa301a3e77f5f6a Mon Sep 17 00:00:00 2001 From: Guillaume Chereau Date: Mon, 20 Apr 2015 23:18:42 +0800 Subject: [PATCH 004/522] add STB_IMAGE_WRITE_STATIC macro This is the same thing than STB_IMAGE_STATIC of stb_image.h. --- stb_image_write.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 46f60b9..7734cbc 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -84,10 +84,16 @@ CREDITS: extern "C" { #endif -extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); -extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); -extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); -extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#define STBIWDEF extern +#endif + +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); #ifdef __cplusplus } @@ -219,7 +225,7 @@ static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, in return f != NULL; } -int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) { int pad = (-x*3) & 3; return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad, @@ -228,7 +234,7 @@ int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *dat 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } -int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) { int has_alpha = (comp == 2 || comp == 4); int colorbytes = has_alpha ? comp-1 : comp; @@ -364,7 +370,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra } } -int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { int i; FILE *f; @@ -693,7 +699,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in return out; } -int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) { FILE *f; int len; From e0e4bd4d861b90282e48bd467865f8c7bb389779 Mon Sep 17 00:00:00 2001 From: fahickman Date: Mon, 11 May 2015 21:38:55 -0700 Subject: [PATCH 005/522] write TGAs with RLE compression --- stb_image_write.h | 134 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 104 insertions(+), 30 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 1048970..b860a74 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -149,6 +149,14 @@ static void writefv(FILE *f, const char *fmt, va_list v) } } +static void writef(FILE *f, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + writefv(f, fmt, v); + va_end(v); +} + static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c) { unsigned char arr[3]; @@ -156,11 +164,42 @@ static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c) fwrite(arr, 3, 1, f); } -static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +static void write_pixel(FILE *f, int rgb_dir, int comp, int write_alpha, int expand_mono, const unsigned char *d) { unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + fwrite(&d[comp - 1], 1, 1, f); + switch (comp) { + case 1: fwrite(d, 1, 1, f); + break; + case 2: if (expand_mono) + write3(f, d[0], d[0], d[0]); // monochrome bmp + else + fwrite(d, 1, 1, f); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + write3(f, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + write3(f, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + fwrite(&d[comp - 1], 1, 1, f); +} + +static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ stbiw_uint32 zero = 0; - int i,j,k, j_end; + int i,j, j_end; if (y <= 0) return; @@ -173,31 +212,7 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, for (; j != j_end; j += vdir) { for (i=0; i < x; ++i) { unsigned char *d = (unsigned char *) data + (j*x+i)*comp; - if (write_alpha < 0) - fwrite(&d[comp-1], 1, 1, f); - switch (comp) { - case 1: fwrite(d, 1, 1, f); - break; - case 2: if (expand_mono) - write3(f, d[0],d[0],d[0]); // monochrome bmp - else - fwrite(d, 1, 1, f); // monochrome TGA - break; - case 4: - if (!write_alpha) { - // composite against pink background - for (k=0; k < 3; ++k) - px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; - write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]); - break; - } - /* FALLTHROUGH */ - case 3: - write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]); - break; - } - if (write_alpha > 0) - fwrite(&d[comp-1], 1, 1, f); + write_pixel(f, rgb_dir, comp, write_alpha, expand_mono, d); } fwrite(&zero,scanline_pad,1,f); } @@ -232,9 +247,68 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat { int has_alpha = (comp == 2 || comp == 4); int colorbytes = has_alpha ? comp-1 : comp; - int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 - return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0, - "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8); + int format = colorbytes < 2 ? 11 : 10; // 3 color channels (RGB/RGBA) = 10, 1 color channel (Y/YA) = 11 + FILE *f; + + if (y < 0 || x < 0) return 0; + f = fopen(filename, "wb"); + if (f) { + int i,j,k; + + writef(f, "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); + + for (j = y - 1; j >= 0; --j) { + unsigned char *line = (unsigned char *) data + j * x * comp; + int run; + + for (i = 0; i < x; i += run) { + unsigned char *first = line + i * comp; + int diff = 1; + run = 1; + + if (i < x - 1) { + ++run; + diff = memcmp(first, line + (i + 1) * comp, comp); + if (diff) { + unsigned char *next = first; + for (k = i + 2; k < x && run < 128; ++k) { + if (memcmp(next, line + k * comp, comp)) { + next += comp; + ++run; + } else { + --run; + break; + } + } + } else { + for (k = i + 2; k < x && run < 128; ++k) { + if (!memcmp(first, line + k * comp, comp)) { + ++run; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = (unsigned char) (run - 1); + fwrite(&header, 1, 1, f); + for (k = 0; k < run; ++k) { + write_pixel(f, -1, comp, has_alpha, 0, first + k * comp); + } + } else { + unsigned char header = (unsigned char) (run - 1) | 0x80; + fwrite(&header, 1, 1, f); + write_pixel(f, -1, comp, has_alpha, 0, first); + } + } + } + + fclose(f); + } + + return f != NULL; } // ************************************************************************************************* From 126ec22867c88917ab3da278e0e126b104f55b00 Mon Sep 17 00:00:00 2001 From: fahickman Date: Thu, 4 Jun 2015 14:04:02 -0700 Subject: [PATCH 006/522] add missing consts --- stb_image_write.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index b860a74..5c1e5f9 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -258,32 +258,32 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat writef(f, "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); for (j = y - 1; j >= 0; --j) { - unsigned char *line = (unsigned char *) data + j * x * comp; - int run; + const unsigned char *row = (unsigned char *) data + j * x * comp; + int len; - for (i = 0; i < x; i += run) { - unsigned char *first = line + i * comp; + for (i = 0; i < x; i += len) { + const unsigned char *begin = row + i * comp; int diff = 1; - run = 1; + len = 1; if (i < x - 1) { - ++run; - diff = memcmp(first, line + (i + 1) * comp, comp); + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); if (diff) { - unsigned char *next = first; - for (k = i + 2; k < x && run < 128; ++k) { - if (memcmp(next, line + k * comp, comp)) { - next += comp; - ++run; + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; } else { - --run; + --len; break; } } } else { - for (k = i + 2; k < x && run < 128; ++k) { - if (!memcmp(first, line + k * comp, comp)) { - ++run; + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; } else { break; } @@ -292,15 +292,15 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat } if (diff) { - unsigned char header = (unsigned char) (run - 1); + unsigned char header = (unsigned char) (len - 1); fwrite(&header, 1, 1, f); - for (k = 0; k < run; ++k) { - write_pixel(f, -1, comp, has_alpha, 0, first + k * comp); + for (k = 0; k < len; ++k) { + write_pixel(f, -1, comp, has_alpha, 0, begin + k * comp); } } else { - unsigned char header = (unsigned char) (run - 1) | 0x80; + unsigned char header = (unsigned char) (len - 129); fwrite(&header, 1, 1, f); - write_pixel(f, -1, comp, has_alpha, 0, first); + write_pixel(f, -1, comp, has_alpha, 0, begin); } } } From b639b6a4680fef7595af4c639fcc1bfa91624bf8 Mon Sep 17 00:00:00 2001 From: Robert Nix Date: Tue, 9 Jun 2015 12:44:50 -0500 Subject: [PATCH 007/522] Don't use __asm int 3; on 64-bit platforms --- stb.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/stb.h b/stb.h index d78c465..03d891e 100644 --- a/stb.h +++ b/stb.h @@ -1021,9 +1021,15 @@ void stb_fatal(char *s, ...) vfprintf(stderr, s, a); va_end(a); fputs("\n", stderr); - #ifdef _WIN32 #ifdef STB_DEBUG + #ifdef _MSC_VER + #ifndef STB_PTR64 __asm int 3; // trap to debugger! + #else + __debugbreak(); + #endif + #else + __builtin_trap(); #endif #endif exit(1); From 0fbc8bec6f613bd91ec07ffc67ab0dae8a458b50 Mon Sep 17 00:00:00 2001 From: Robert Nix Date: Tue, 9 Jun 2015 12:46:31 -0500 Subject: [PATCH 008/522] Don't truncate pointers to 4 bytes on 64-bit --- stb.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/stb.h b/stb.h index 03d891e..bc0114e 100644 --- a/stb.h +++ b/stb.h @@ -5831,14 +5831,19 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) { char **results = NULL; char buffer[512], with_slash[512]; - int n; + size_t n; #ifdef _MSC_VER stb__wchar *ws; struct _wfinddata_t data; + #ifdef _WIN64 + const intptr_t none = -1; + intptr_t z; + #else const long none = -1; long z; - #else + #endif + #else // !_MSC_VER const DIR *none = NULL; DIR *z; #endif @@ -6812,7 +6817,11 @@ static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *acti int n; struct _wfinddata_t c_file; + #ifdef STB_PTR64 + intptr_t hFile; + #else long hFile; + #endif stb__wchar full_path[1024]; int has_slash; From 51415dea6e790741076857b03a19532619149abf Mon Sep 17 00:00:00 2001 From: Robert Nix Date: Tue, 9 Jun 2015 12:47:50 -0500 Subject: [PATCH 009/522] Fix 64-bit compile for pointer set --- stb.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stb.h b/stb.h index bc0114e..24cea76 100644 --- a/stb.h +++ b/stb.h @@ -7353,7 +7353,7 @@ STB_EXTERN void ** stb_ps_fastlist(stb_ps *ps, int *count); // but some entries of the list may be invalid; // test with 'stb_ps_fastlist_valid(x)' -#define stb_ps_fastlist_valid(x) ((unsigned int) (x) > 1) +#define stb_ps_fastlist_valid(x) ((stb_uinta) (x) > 1) #ifdef STB_DEFINE @@ -7374,8 +7374,6 @@ typedef struct #define GetBucket(p) ((stb_ps_bucket *) ((char *) (p) - STB_ps_bucket)) #define EncodeBucket(p) ((stb_ps *) ((char *) (p) + STB_ps_bucket)) -typedef char stb__verify_bucket_heap_size[sizeof(stb_ps_bucket) == 16]; - static void stb_bucket_free(stb_ps_bucket *b) { free(b); From 8702dce4d646ca80e50c33e9e190b210a77cac14 Mon Sep 17 00:00:00 2001 From: r-lyeh Date: Sat, 13 Jun 2015 13:50:31 +0200 Subject: [PATCH 010/522] msvc 64-bit fixes --- stb.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb.h b/stb.h index 671ffcd..241e721 100644 --- a/stb.h +++ b/stb.h @@ -1023,7 +1023,7 @@ void stb_fatal(char *s, ...) fputs("\n", stderr); #ifdef _WIN32 #ifdef STB_DEBUG - __asm int 3; // trap to debugger! + __debugbreak; // trap to debugger! #endif #endif exit(1); @@ -1401,7 +1401,7 @@ int stb_is_pow2(unsigned int n) int stb_log2_floor(unsigned int n) { #if _MSC_VER > 1700 - DWORD i; + unsigned int i; _BitScanReverse(&i, n); return i != 0 ? i : -1; #else @@ -7359,7 +7359,7 @@ typedef struct #define GetBucket(p) ((stb_ps_bucket *) ((char *) (p) - STB_ps_bucket)) #define EncodeBucket(p) ((stb_ps *) ((char *) (p) + STB_ps_bucket)) -typedef char stb__verify_bucket_heap_size[sizeof(stb_ps_bucket) == 16]; +typedef char stb__verify_bucket_heap_size[sizeof(stb_ps_bucket) >= 16]; static void stb_bucket_free(stb_ps_bucket *b) { From 693772ed02dac18c6ff740e6957bd95dd4bd34c2 Mon Sep 17 00:00:00 2001 From: blackpawn Date: Mon, 22 Jun 2015 19:45:35 -0700 Subject: [PATCH 011/522] OSX 64bit fixes Check for __LP64__ preprocessor define for 64bit. Allocator fix for 64bit. --- stb.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb.h b/stb.h index 671ffcd..d9c3233 100644 --- a/stb.h +++ b/stb.h @@ -323,7 +323,7 @@ typedef char stb__testsize2_64[sizeof(stb_uint64)==8 ? 1 : -1]; // add platform-specific ways of checking for sizeof(char*) == 8, // and make those define STB_PTR64 -#if defined(_WIN64) || defined(__x86_64__) || defined(__ia64__) +#if defined(_WIN64) || defined(__x86_64__) || defined(__ia64__) || defined(__LP64__) #define STB_PTR64 #endif @@ -2561,7 +2561,8 @@ void stb_malloc_validate(void *p, void *parent) static void * stb__try_chunk(stb__chunk *c, int size, int align, int pre_align) { char *memblock = (char *) (c+1), *q; - int iq, start_offset; + stb_inta iq; + int start_offset; // we going to allocate at the end of the chunk, not the start. confusing, // but it means we don't need both a 'limit' and a 'cur', just a 'cur'. From 2762b410fed870cc5db29a4e34e4eedaaf84f368 Mon Sep 17 00:00:00 2001 From: Michaelangel007 Date: Tue, 30 Jun 2015 08:02:24 -0600 Subject: [PATCH 012/522] Fix unused vars warning in stbi_is_hdr_from_file stbi_is_hdr_from_callbacks --- stb_image.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stb_image.h b/stb_image.h index d0fa9c2..ea5cc9f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1153,6 +1153,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f) stbi__start_file(&s,f); return stbi__hdr_test(&s); #else + STBI_NOTUSED(f); return 0; #endif } @@ -1165,6 +1166,8 @@ STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); return stbi__hdr_test(&s); #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); return 0; #endif } From c11532b8723d548a2444d67691b2cd27a1111152 Mon Sep 17 00:00:00 2001 From: Michaelangel007 Date: Tue, 30 Jun 2015 08:54:14 -0600 Subject: [PATCH 013/522] Cleanup unused functions --- stb_image.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index ea5cc9f..57a24d3 100644 --- a/stb_image.h +++ b/stb_image.h @@ -989,6 +989,7 @@ static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *com return result; } +#ifndef STBI_NO_HDR static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) { if (stbi__vertically_flip_on_load && result != NULL) { @@ -1009,7 +1010,7 @@ static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, in } } } - +#endif #ifndef STBI_NO_STDIO @@ -1288,17 +1289,22 @@ static stbi__uint32 stbi__get32be(stbi__context *s) return (z << 16) + stbi__get16be(s); } +#if defined (STBI_NO_BMP) && (STBI_NO_TGA) && (STBI_NO_GIF) +#else static int stbi__get16le(stbi__context *s) { int z = stbi__get8(s); return z + (stbi__get8(s) << 8); } +#endif +#ifndef STBI_NO_BMP static stbi__uint32 stbi__get32le(stbi__context *s) { stbi__uint32 z = stbi__get16le(s); return z + (stbi__get16le(s) << 16); } +#endif #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings From be8284de7e5cc560185daa35d92f7ea691a041b8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 30 Jun 2015 20:02:41 -0600 Subject: [PATCH 014/522] stb_wingraph.h: missing lib pragmas for completeness --- tests/oversample/stb_wingraph.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/oversample/stb_wingraph.h b/tests/oversample/stb_wingraph.h index ee16923..94798eb 100644 --- a/tests/oversample/stb_wingraph.h +++ b/tests/oversample/stb_wingraph.h @@ -25,6 +25,8 @@ #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glu32.lib") #pragma comment(lib, "winmm.lib") + #pragma comment(lib, "gdi32.lib") + #pragma comment(lib, "user32.lib") #endif #ifdef __cplusplus From 65ebe75124a69193748021fa96eaa6cf660db9b9 Mon Sep 17 00:00:00 2001 From: Liam Chasteen Date: Thu, 2 Jul 2015 11:50:32 -0700 Subject: [PATCH 015/522] Tweaked to enable compilation under MinGW. --- stb.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/stb.h b/stb.h index 671ffcd..3c70dc3 100644 --- a/stb.h +++ b/stb.h @@ -190,6 +190,9 @@ Parenthesized items have since been removed. #include // need FILE #include // stb_define_hash needs memcpy/memset #include // stb_dirtree +#ifdef __MINGW32__ + #include // O_RDWR +#endif #ifdef STB_PERSONAL typedef int Bool; @@ -1395,7 +1398,7 @@ int stb_is_pow2(unsigned int n) // tricky use of 4-bit table to identify 5 bit positions (note the '-1') // 3-bit table would require another tree level; 5-bit table wouldn't save one -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW32__) #pragma warning(push) #pragma warning(disable: 4035) // disable warning about no return value int stb_log2_floor(unsigned int n) @@ -5049,7 +5052,7 @@ void stb_fwrite32(FILE *f, stb_uint32 x) fwrite(&x, 4, 1, f); } -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__MINGW32__) #define stb__stat _stat #else #define stb__stat stat @@ -5389,7 +5392,11 @@ FILE * stb_fopen(char *filename, char *mode) #else { strcpy(temp_full+p, "stmpXXXXXX"); - int fd = mkstemp(temp_full); + #ifdef __MINGW32__ + int fd = open(mktemp(temp_full), O_RDWR); + #else + int fd = mkstemp(temp_full); + #endif if (fd == -1) return NULL; f = fdopen(fd, mode); if (f == NULL) { @@ -6988,7 +6995,7 @@ stb_dirtree *stb_dirtree_get_dir(char *dir, char *cache_dir) stb_sha1(sha, (unsigned char *) dir_lower, strlen(dir_lower)); strcpy(cache_file, cache_dir); s = cache_file + strlen(cache_file); - if (s[-1] != '//' && s[-1] != '\\') *s++ = '/'; + if (s[-1] != '/' && s[-1] != '\\') *s++ = '/'; strcpy(s, "dirtree_"); s += strlen(s); for (i=0; i < 8; ++i) { From 80a0e90d53abf30d71fe6f40e243253cbb2aadba Mon Sep 17 00:00:00 2001 From: fahickman Date: Fri, 3 Jul 2015 14:27:29 -0700 Subject: [PATCH 016/522] TGA RLE flag and regression fix Add requested flag for controlling TGA RLE compression and fix a regression when writing monochrome TGAs. --- stb_image_write.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 5c1e5f9..e5d7bd5 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -129,6 +129,8 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; +static int stbi__write_tga_with_rle = 1; + static void writefv(FILE *f, const char *fmt, va_list v) { while (*fmt) { @@ -247,15 +249,20 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat { int has_alpha = (comp == 2 || comp == 4); int colorbytes = has_alpha ? comp-1 : comp; - int format = colorbytes < 2 ? 11 : 10; // 3 color channels (RGB/RGBA) = 10, 1 color channel (Y/YA) = 11 + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 FILE *f; + if (!stbi__write_tga_with_rle) { + return outfile(filename, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } + if (y < 0 || x < 0) return 0; f = fopen(filename, "wb"); if (f) { int i,j,k; - writef(f, "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); + writef(f, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); for (j = y - 1; j >= 0; --j) { const unsigned char *row = (unsigned char *) data + j * x * comp; From fcfa17b847061d379893d083ef02ea743bb62c6d Mon Sep 17 00:00:00 2001 From: rmitton Date: Mon, 6 Jul 2015 13:32:40 -0700 Subject: [PATCH 017/522] Fixed double-free in JPEG allocation It was incorrectly setting the wrong field to NULL, causing it to get freed again later. --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index d0fa9c2..293be74 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2739,7 +2739,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) if (z->img_comp[i].raw_data == NULL) { for(--i; i >= 0; --i) { STBI_FREE(z->img_comp[i].raw_data); - z->img_comp[i].data = NULL; + z->img_comp[i].raw_data = NULL; } return stbi__err("outofmem", "Out of memory"); } From a371b204f57e49d3799630b7f2074eb99eedb5ef Mon Sep 17 00:00:00 2001 From: rmitton Date: Tue, 7 Jul 2015 15:15:38 -0700 Subject: [PATCH 018/522] Added support for 16-bit PSD loading. This extends the current PSD loader to add support for 16-bit images, by quantizing them down to 8-bit upon load. --- stb_image.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index d0fa9c2..2981df3 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5054,6 +5054,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int int pixelCount; int channelCount, compression; int channel, i, count, len; + int bitdepth; int w,h; stbi_uc *out; @@ -5078,8 +5079,9 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int w = stbi__get32be(s); // Make sure the depth is 8 bits. - if (stbi__get16be(s) != 8) - return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 bit"); + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); // Make sure the color mode is RGB. // Valid options are: @@ -5191,8 +5193,13 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int *p = channel == 3 ? 255 : 0; } else { // Read the data. - for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get8(s); + if (bitdepth == 16) { + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi__get16le(s) + 127) >> 8; + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } } } } From 608cbec1f59a72fcd2b6862a98daaabe9c001f28 Mon Sep 17 00:00:00 2001 From: rmitton Date: Tue, 7 Jul 2015 15:47:37 -0700 Subject: [PATCH 019/522] Fixed overflow for high values. 0xffff would accidentally round to 0x10000. --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 2981df3..e1c29b8 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5195,7 +5195,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int // Read the data. if (bitdepth == 16) { for (i = 0; i < pixelCount; i++, p += 4) - *p = (stbi__get16le(s) + 127) >> 8; + *p = stbi__get16le(s) * 255 / 65535; } else { for (i = 0; i < pixelCount; i++, p += 4) *p = stbi__get8(s); From 6645ea5915833f6a89f51c3d95fcb8f50948c7fa Mon Sep 17 00:00:00 2001 From: rmitton Date: Fri, 24 Jul 2015 12:00:09 -0700 Subject: [PATCH 020/522] Fixed stupid endianness bug. Incorrect endianness hilariously doesn't manifest _if_ the original image was upconverted from 8-bit to 16-bit. --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index e1c29b8..5d54bd1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5195,7 +5195,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int // Read the data. if (bitdepth == 16) { for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get16le(s) * 255 / 65535; + *p = stbi__get16be(s) * 255 / 65535; } else { for (i = 0; i < pixelCount; i++, p += 4) *p = stbi__get8(s); From 5305ffbe49b3b993f33b6251b07a116ceafeddac Mon Sep 17 00:00:00 2001 From: Joshua Sheard Date: Wed, 29 Jul 2015 17:00:44 +0000 Subject: [PATCH 021/522] Include math.h for ceil() --- stb_easy_font.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_easy_font.h b/stb_easy_font.h index daa0c3e..fa70632 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -88,6 +88,7 @@ void print_string(float x, float y, char *text, float r, float g, float b) #define INCLUDE_STB_EASY_FONT_H #include +#include struct { unsigned char advance; From c1cb414bc6dd8e009c2d2e23665e742cfe017b4f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 1 Aug 2015 04:17:38 -0700 Subject: [PATCH 022/522] stb_voxel_render.h version 0.82 --- stb_voxel_render.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 1482113..040c028 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -1,4 +1,4 @@ -// stb_voxel_render.h - v0.81 - Sean Barrett, 2015 - public domain +// stb_voxel_render.h - v0.82 - Sean Barrett, 2015 - public domain // // This library helps render large-scale "voxel" worlds for games, // in this case, one with blocks that can have textures and that @@ -191,6 +191,7 @@ // VERSION HISTORY // // 0.82 (2015-08-01) added input.packed_compact to store rot, vheight & texlerp efficiently +// fix broken tex_overlay2 // 0.81 (2015-05-28) fix broken STBVOX_CONFIG_OPTIMIZED_VHEIGHT // 0.80 (2015-04-11) fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING refactoring // change STBVOX_MAKE_LIGHTING to STBVOX_MAKE_LIGHTING_EXT so From 59c353962ace3a47bbd782a0cbb00f122c23d127 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 1 Aug 2015 04:18:27 -0700 Subject: [PATCH 023/522] update readme version numbers --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6694d03..ea743fa 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,15 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**stb_vorbis.c** | 1.05 | audio | 5445 | decode ogg vorbis files from file/memory to float/16-bit signed output +**stb_vorbis.c** | 1.05 | audio | 5459 | decode ogg vorbis files from file/memory to float/16-bit signed output **stb_image.h** | 2.06 | graphics | 6437 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.06 | graphics | 2632 | parse, decode, and rasterize characters from truetype fonts +**stb_truetype.h** | 1.07 | graphics | 3220 | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 0.98 | graphics | 730 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2585 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.06 | graphics | 560 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 210 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **stb_textedit.h** | 1.6 | UI | 1290 | guts of a text editor for games etc implementing them from scratch -**stb_voxel_render.h** | 0.81 | 3D graphics | 3644 | Minecraft-esque voxel rendering "engine" with many more features +**stb_voxel_render.h** | 0.82 | 3D graphics | 3739 | Minecraft-esque voxel rendering "engine" with many more features **stb_dxt.h** | 1.04 | 3D graphics | 624 | Fabian "ryg" Giesen's real-time DXT compressor **stb_perlin.h** | 0.2 | 3D graphics | 175 | revised Perlin noise (3D input, 1D output) **stb_easy_font.h** | 0.5 | 3D graphics | 220 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc @@ -27,7 +27,7 @@ library | lastest version | category | LoC | description **stb_leakcheck.h** | 0.2 | misc | 117 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 45274 +Total lines of C code: 45971 FAQ From 9e9ce0ab918b38f609472ef98fa11a3955c29b92 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:46:04 -0400 Subject: [PATCH 024/522] Added public domain license text --- stb.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/stb.h b/stb.h index 671ffcd..e0e80d2 100644 --- a/stb.h +++ b/stb.h @@ -1,5 +1,4 @@ /* stb.h - v2.24 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h - no warranty is offered or implied; use this code at your own risk This is a single header file with a bunch of useful utilities for getting stuff done in C/C++. @@ -166,6 +165,13 @@ Version History (stb_array), (stb_arena) Parenthesized items have since been removed. + +LICENSE + +This software is in the public domain. Where that dedication is not +recognized, you are granted a perpetual, irrevocable license to copy, +distribute, and modify this file as you see fit. + */ #ifndef STB__INCLUDE_STB_H From 4ab69f3b2c294b8d1117a71cca0e1c57ac368c3b Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:46:52 -0400 Subject: [PATCH 025/522] Added public domain license text --- stb_c_lexer.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index f0fa5c4..1cf53e4 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -28,6 +28,12 @@ // - haven't implemented octal/hex character constants // - haven't implemented support for unicode CLEX_char // - need to expand error reporting so you don't just get "CLEX_parse_error" +// +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. #ifndef STB_C_LEXER_DEFINITIONS // to change the default parsing rules, copy the following lines From 242b1fe37a23b446913a16c829a5793cb5456b9c Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:48:08 -0400 Subject: [PATCH 026/522] Added public domain license text --- stb_divide.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stb_divide.h b/stb_divide.h index 8a853d3..4e35abe 100644 --- a/stb_divide.h +++ b/stb_divide.h @@ -75,6 +75,12 @@ // by the euclidean division operator we define, so it's possibly not // always true. If any such platform turns up, we can add more cases. // (Possibly only stb_div_trunc currently relies on property (b).) +// +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. #ifndef INCLUDE_STB_DIVIDE_H From 55ff60818ed701946e6b3897ffa29e3dba746ec3 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:48:37 -0400 Subject: [PATCH 027/522] Added public domain license text --- stb_dxt.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stb_dxt.h b/stb_dxt.h index bec7279..418ba65 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -16,6 +16,12 @@ // v1.02 - (stb) fix alpha encoding bug // v1.01 - (stb) fix bug converting to RGB that messed up quality, thanks ryg & cbloom // v1.00 - (stb) first release +// +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. #ifndef STB_INCLUDE_STB_DXT_H #define STB_INCLUDE_STB_DXT_H From fa464b33acda9d81b44b0b2c1cc470209b520f4d Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:49:15 -0400 Subject: [PATCH 028/522] Added public domain license text --- stb_easy_font.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stb_easy_font.h b/stb_easy_font.h index daa0c3e..b83061b 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -68,6 +68,12 @@ // Here's sample code for old OpenGL; it's a lot more complicated // to make work on modern APIs, and that's your problem. // +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. +// #if 0 void print_string(float x, float y, char *text, float r, float g, float b) { From 6695bc4e180a4aac7721a54f1a51d06f53f2679e Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:50:51 -0400 Subject: [PATCH 029/522] Added public domain license text --- stb_herringbone_wang_tile.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stb_herringbone_wang_tile.h b/stb_herringbone_wang_tile.h index 6ef0e60..de7fb20 100644 --- a/stb_herringbone_wang_tile.h +++ b/stb_herringbone_wang_tile.h @@ -1,8 +1,11 @@ /* stbhw - v0.6 - http://nothings.org/gamedev/herringbone Herringbone Wang Tile Generator - Sean Barrett 2014 - public domain - This file is in the public domain. In case that declaration is ineffective, - you are also granted a license to use and modify it without restriction. +== LICENSE ============================== + +This software is in the public domain. Where that dedication is not +recognized, you are granted a perpetual, irrevocable license to copy, +distribute, and modify this file as you see fit. == WHAT IT IS =========================== From f0e456b809660f487b9f053ff5c0835800df6068 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:52:12 -0400 Subject: [PATCH 030/522] Added public domain license text --- stb_image.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stb_image.h b/stb_image.h index d0fa9c2..9c23942 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,5 +1,4 @@ /* stb_image - v2.06 - public domain image loader - http://nothings.org/stb_image.h - no warranty implied; use at your own risk Do this: #define STB_IMAGE_IMPLEMENTATION @@ -204,10 +203,11 @@ Joseph Thomson Phil Jordan -License: - This software is in the public domain. Where that dedication is not - recognized, you are granted a perpetual, irrevocable license to copy - and modify this file however you want. +LICENSE + +This software is in the public domain. Where that dedication is not +recognized, you are granted a perpetual, irrevocable license to copy, +distribute, and modify this file as you see fit. */ From 1d48782e1d441fb7f4c7b960b7198dd1d7adc4a4 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:53:00 -0400 Subject: [PATCH 031/522] Added public domain license text --- stb_image_resize.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index bcca92c..4ce7ddb 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -159,9 +159,10 @@ 0.90 (2014-09-17) first released version LICENSE - This software is in the public domain. Where that dedication is not - recognized, you are granted a perpetual, irrevocable license to copy - and modify this file as you see fit. + + This software is in the public domain. Where that dedication is not + recognized, you are granted a perpetual, irrevocable license to copy, + distribute, and modify this file as you see fit. TODO Don't decode all of the image data when only processing a partial tile From 45b27d8a9ccd0393ef1be39dbd98e993a8eef313 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:54:05 -0400 Subject: [PATCH 032/522] Added public domain license text --- stb_image_write.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 1048970..f3b2e62 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,6 +1,5 @@ /* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 - no warranty implied; use at your own risk Before #including, @@ -75,6 +74,12 @@ CREDITS: Tim Kelsey bugfixes: github:Chribba + +LICENSE + +This software is in the public domain. Where that dedication is not +recognized, you are granted a perpetual, irrevocable license to copy, +distribute, and modify this file as you see fit. */ #ifndef INCLUDE_STB_IMAGE_WRITE_H From 5a7d524fd8aa342a4bd65753ba13de2fa21e40e6 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:54:27 -0400 Subject: [PATCH 033/522] Added public domain license text --- stb_leakcheck.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stb_leakcheck.h b/stb_leakcheck.h index a75df7c..389eee3 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -1,4 +1,9 @@ // stb_leakcheck.h - v0.2 - quick & dirty malloc leak-checking - public domain +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. #ifdef STB_LEAKCHECK_IMPLEMENTATION #undef STB_LEAKCHECK_IMPLEMENTATION // don't implenment more than once From 35e2f7e7399104696c52189b59b2c7bf975fa622 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:54:57 -0400 Subject: [PATCH 034/522] Added public domain license text --- stb_perlin.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stb_perlin.h b/stb_perlin.h index 8ff7419..399e438 100644 --- a/stb_perlin.h +++ b/stb_perlin.h @@ -1,6 +1,13 @@ // stb_perlin.h - v0.2 - perlin noise // public domain single-file C implementation by Sean Barrett // +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. +// +// // to create the implementation, // #define STB_PERLIN_IMPLEMENTATION // in *one* C/CPP file that includes this file. From 7effe64e456f8d7eb21881fa1568e9174d04832d Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:55:35 -0400 Subject: [PATCH 035/522] Added public domain license text --- stb_rect_pack.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index 63a5b15..ac13df6 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -36,6 +36,12 @@ // 0.05: added STBRP_ASSERT to allow replacing assert // 0.04: fixed minor bug in STBRP_LARGE_RECTS support // 0.01: initial release +// +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. ////////////////////////////////////////////////////////////////////////////// // From 76edb4ec4eae1999a9dde4d9d92bc664a9570c97 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:56:04 -0400 Subject: [PATCH 036/522] Added public domain license text --- stb_textedit.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 1f78048..b8309ff 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -17,9 +17,9 @@ // // LICENSE // -// This software has been placed in the public domain by its author. -// Where that dedication is not recognized, you are granted a perpetual, -// irrevocable license to copy and modify this file as you see fit. +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. // // // DEPENDENCIES From 4727cdd8c018a3f4b107f46292653142e7ae027c Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:56:45 -0400 Subject: [PATCH 037/522] Added public domain license text --- stb_tilemap_editor.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index bd22a4d..3417bee 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1,5 +1,5 @@ // stb_tilemap_editor.h - v0.35 - Sean Barrett - http://nothings.org/stb -// placed in the public domain - not copyrighted - first released 2014-09 +// first released 2014-09 // // Embeddable tilemap editor for C/C++ // @@ -313,9 +313,9 @@ // // LICENSE // -// This software has been placed in the public domain by its author. -// Where that dedication is not recognized, you are granted a perpetual, -// irrevocable license to copy and modify this file as you see fit. +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. From f844b2dbd28ac47537b14b3b55396b1c019df346 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:57:53 -0400 Subject: [PATCH 038/522] Added public domain license text --- stb_vorbis.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index c8d9aad..8188724 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -4,8 +4,11 @@ // Written by Sean Barrett in 2007, last updated in 2014 // Sponsored by RAD Game Tools. // -// Placed in the public domain April 2007 by the author: no copyright -// is claimed, and you may use it for any purpose you like. +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. // // No warranty for any purpose is expressed or implied by the author (nor // by RAD Game Tools). Report bugs and send enhancements to the author. From 85d0adda25cc0133879144b066148a38575e7206 Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:59:03 -0400 Subject: [PATCH 039/522] Added public domain license text --- stb_voxel_render.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 040c028..b8ab3ba 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -210,6 +210,13 @@ // stb_voxel_render 20-byte quads 2015/01 // zmc engine 32-byte quads 2013/12 // zmc engine 96-byte quads 2011/10 +// +// +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. #ifndef INCLUDE_STB_VOXEL_RENDER_H #define INCLUDE_STB_VOXEL_RENDER_H From 594502e5fabe1081f9df6e33ece157104c80145f Mon Sep 17 00:00:00 2001 From: Ryan Whitworth Date: Sat, 1 Aug 2015 14:59:39 -0400 Subject: [PATCH 040/522] Added public domain license text --- stretchy_buffer.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stretchy_buffer.h b/stretchy_buffer.h index a89be09..b99c685 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -161,6 +161,12 @@ // The details are trivial and implementation is straightforward; // the main trick is in realizing in the first place that it's // possible to do this in a generic, type-safe way in C. +// +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. #ifndef STB_STRETCHY_BUFFER_H_INCLUDED #define STB_STRETCHY_BUFFER_H_INCLUDED From c9859afcf9dde9edd85e05dd1feb27aaaa92fb03 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 1 Aug 2015 23:53:49 -0700 Subject: [PATCH 041/522] reverse some of the public-domain-license changes that I didn't actually want --- stb.h | 1 + stb_image.h | 1 + stb_image_write.h | 2 +- stb_tilemap_editor.h | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/stb.h b/stb.h index e0e80d2..f5fab16 100644 --- a/stb.h +++ b/stb.h @@ -1,4 +1,5 @@ /* stb.h - v2.24 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h + no warranty is offered or implied; use this code at your own risk This is a single header file with a bunch of useful utilities for getting stuff done in C/C++. diff --git a/stb_image.h b/stb_image.h index 9c23942..55edc3e 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,5 @@ /* stb_image - v2.06 - public domain image loader - http://nothings.org/stb_image.h + no warranty implied; use at your own risk Do this: #define STB_IMAGE_IMPLEMENTATION diff --git a/stb_image_write.h b/stb_image_write.h index f3b2e62..59052f9 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,6 +1,6 @@ /* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 - + no warranty implied; use at your own risk Before #including, diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 3417bee..73d24e8 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1,5 +1,5 @@ // stb_tilemap_editor.h - v0.35 - Sean Barrett - http://nothings.org/stb -// first released 2014-09 +// placed in the public domain - not copyrighted - first released 2014-09 // // Embeddable tilemap editor for C/C++ // From 23dfb8c06b31cdf746561b727e3f2db43b57eb13 Mon Sep 17 00:00:00 2001 From: urraka Date: Mon, 3 Aug 2015 22:59:16 -0300 Subject: [PATCH 042/522] GIF loading improvements. - Fixed possible memory leak. - Fix for transparent backgrounds. - Adapted internal function to allow proper animation loading. --- stb_image.h | 81 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/stb_image.h b/stb_image.h index d0fa9c2..d1333a1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5438,8 +5438,8 @@ typedef struct typedef struct { int w,h; - stbi_uc *out; // output buffer (always 4 components) - int flags, bgindex, ratio, transparent, eflags; + stbi_uc *out, *old_out; // output buffer (always 4 components) + int flags, bgindex, ratio, transparent, eflags, delay; stbi_uc pal[256][4]; stbi_uc lpal[256][4]; stbi__gif_lzw codes[4096]; @@ -5634,17 +5634,18 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) } } -static void stbi__fill_gif_background(stbi__gif *g) +static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1) { - int i; + int x, y; stbi_uc *c = g->pal[g->bgindex]; - // @OPTIMIZE: write a dword at a time - for (i = 0; i < g->w * g->h * 4; i += 4) { - stbi_uc *p = &g->out[i]; - p[0] = c[2]; - p[1] = c[1]; - p[2] = c[0]; - p[3] = c[3]; + for (y = y0; y < y1; y += 4 * g->w) { + for (x = x0; x < x1; x += 4) { + stbi_uc *p = &g->out[y + x]; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = 0; + } } } @@ -5652,27 +5653,40 @@ static void stbi__fill_gif_background(stbi__gif *g) static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) { int i; - stbi_uc *old_out = 0; + stbi_uc *prev_out = 0; - if (g->out == 0) { - if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header - g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); - if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); - stbi__fill_gif_background(g); - } else { - // animated-gif-only path - if (((g->eflags & 0x1C) >> 2) == 3) { - old_out = g->out; - g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); - if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); - memcpy(g->out, old_out, g->w*g->h*4); - } + if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) + return 0; // stbi__g_failure_reason set by stbi__gif_header + + prev_out = g->out; + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + switch ((g->eflags & 0x1C) >> 2) { + case 0: // unspecified (also always used on 1st frame) + stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h); + break; + case 1: // do not dispose + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + g->old_out = prev_out; + break; + case 2: // dispose to background + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y); + break; + case 3: // dispose to previous + if (g->old_out) { + for (i = g->start_y; i < g->max_y; i += 4 * g->w) + memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x); + } + break; } for (;;) { switch (stbi__get8(s)) { case 0x2C: /* Image Descriptor */ { + int prev_trans = -1; stbi__int32 x, y, w, h; stbi_uc *o; @@ -5705,10 +5719,10 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); g->color_table = (stbi_uc *) g->lpal; } else if (g->flags & 0x80) { - for (i=0; i < 256; ++i) // @OPTIMIZE: stbi__jpeg_reset only the previous transparent - g->pal[i][3] = 255; - if (g->transparent >= 0 && (g->eflags & 0x01)) + if (g->transparent >= 0 && (g->eflags & 0x01)) { + prev_trans = g->pal[g->transparent][3]; g->pal[g->transparent][3] = 0; + } g->color_table = (stbi_uc *) g->pal; } else return stbi__errpuc("missing color table", "Corrupt GIF"); @@ -5716,8 +5730,9 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i o = stbi__process_gif_raster(s, g); if (o == NULL) return NULL; - if (req_comp && req_comp != 4) - o = stbi__convert_format(o, 4, req_comp, g->w, g->h); + if (prev_trans != -1) + g->pal[g->transparent][3] = prev_trans; + return o; } @@ -5728,7 +5743,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i len = stbi__get8(s); if (len == 4) { g->eflags = stbi__get8(s); - stbi__get16le(s); // delay + g->delay = stbi__get16le(s); g->transparent = stbi__get8(s); } else { stbi__skip(s, len); @@ -5760,7 +5775,11 @@ static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int if (u) { *x = g.w; *y = g.h; + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); } + else if (g.out) + STBI_FREE(g.out); return u; } From 0c0a619ca489d121e83bd08b406492c5de67b191 Mon Sep 17 00:00:00 2001 From: rwhitworth Date: Wed, 5 Aug 2015 22:27:53 -0400 Subject: [PATCH 043/522] Updated to compile with Visual Studio 2015 --- stb.h | 9 +- stb_easy_font.h | 4 + stb_leakcheck.h | 2 + stb_tilemap_editor.h | 6 + stb_vorbis.h | 5463 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 5483 insertions(+), 1 deletion(-) create mode 100644 stb_vorbis.h diff --git a/stb.h b/stb.h index 671ffcd..8b90c2f 100644 --- a/stb.h +++ b/stb.h @@ -186,6 +186,13 @@ Parenthesized items have since been removed. #endif #endif +#ifdef _WIN32 + #define _CRT_SECURE_NO_WARNINGS + #define _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NON_CONFORMING_SWPRINTFS + #include // _BitScanReverse +#endif + #include // stdlib could have min/max #include // need FILE #include // stb_define_hash needs memcpy/memset @@ -1401,7 +1408,7 @@ int stb_is_pow2(unsigned int n) int stb_log2_floor(unsigned int n) { #if _MSC_VER > 1700 - DWORD i; + unsigned long i; _BitScanReverse(&i, n); return i != 0 ? i : -1; #else diff --git a/stb_easy_font.h b/stb_easy_font.h index daa0c3e..f63bda8 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -84,6 +84,10 @@ void print_string(float x, float y, char *text, float r, float g, float b) } #endif +#ifdef _WIN32 + #include +#endif + #ifndef INCLUDE_STB_EASY_FONT_H #define INCLUDE_STB_EASY_FONT_H diff --git a/stb_leakcheck.h b/stb_leakcheck.h index a75df7c..a51d4f1 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -10,6 +10,8 @@ #undef realloc #endif +#include +#include #include #include #include diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index bd22a4d..e4504af 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -326,6 +326,12 @@ #ifndef STB_TILEMAP_INCLUDE_STB_TILEMAP_EDITOR_H #define STB_TILEMAP_INCLUDE_STB_TILEMAP_EDITOR_H +#ifdef _WIN32 + #define _CRT_SECURE_NO_WARNINGS + #include + #include +#endif + typedef struct stbte_tilemap stbte_tilemap; // these are the drawmodes used in STBTE_DRAW_TILE diff --git a/stb_vorbis.h b/stb_vorbis.h new file mode 100644 index 0000000..e71f0b8 --- /dev/null +++ b/stb_vorbis.h @@ -0,0 +1,5463 @@ +// Ogg Vorbis audio decoder - v1.05 - public domain +// http://nothings.org/stb_vorbis/ +// +// Written by Sean Barrett in 2007, last updated in 2014 +// Sponsored by RAD Game Tools. +// +// Placed in the public domain April 2007 by the author: no copyright +// is claimed, and you may use it for any purpose you like. +// +// No warranty for any purpose is expressed or implied by the author (nor +// by RAD Game Tools). Report bugs and send enhancements to the author. +// +// Limitations: +// +// - seeking not supported except manually via PUSHDATA api +// - floor 0 not supported (used in old ogg vorbis files pre-2004) +// - lossless sample-truncation at beginning ignored +// - cannot concatenate multiple vorbis streams +// - sample positions are 32-bit, limiting seekable 192Khz +// files to around 6 hours (Ogg supports 64-bit) +// +// Bugfix/warning contributors: +// Terje Mathisen Niklas Frykholm Andy Hill +// Casey Muratori John Bolton Gargaj +// Laurent Gomila Marc LeBlanc Ronny Chevalier +// Bernhard Wodo Evan Balster "alxprd"@github +// Tom Beaumont Ingo Leitgeb Nicolas Guillemot +// (If you reported a bug but do not appear in this list, it is because +// someone else reported the bug before you. There were too many of you to +// list them all because I was lax about updating for a long time, sorry.) +// +// Partial history: +// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant +// 1.04 - 2014/08/27 - fix missing const-correct case in API +// 1.03 - 2014/08/07 - warning fixes +// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows +// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct) +// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel; +// (API change) report sample rate for decode-full-file funcs +// 0.99996 - - bracket #include for macintosh compilation +// 0.99995 - - avoid alias-optimization issue in float-to-int conversion +// +// See end of file for full version history. + + +////////////////////////////////////////////////////////////////////////////// +// +// HEADER BEGINS HERE +// + +#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H +#define STB_VORBIS_INCLUDE_STB_VORBIS_H + +#ifdef _WIN32 + #define _CRT_SECURE_NO_WARNINGS +#endif + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) +#define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/////////// THREAD SAFETY + +// Individual stb_vorbis* handles are not thread-safe; you cannot decode from +// them from multiple threads at the same time. However, you can have multiple +// stb_vorbis* handles and decode from them independently in multiple thrads. + + +/////////// MEMORY ALLOCATION + +// normally stb_vorbis uses malloc() to allocate memory at startup, +// and alloca() to allocate temporary memory during a frame on the +// stack. (Memory consumption will depend on the amount of setup +// data in the file and how you set the compile flags for speed +// vs. size. In my test files the maximal-size usage is ~150KB.) +// +// You can modify the wrapper functions in the source (setup_malloc, +// setup_temp_malloc, temp_malloc) to change this behavior, or you +// can use a simpler allocation model: you pass in a buffer from +// which stb_vorbis will allocate _all_ its memory (including the +// temp memory). "open" may fail with a VORBIS_outofmem if you +// do not pass in enough data; there is no way to determine how +// much you do need except to succeed (at which point you can +// query get_info to find the exact amount required. yes I know +// this is lame). +// +// If you pass in a non-NULL buffer of the type below, allocation +// will occur from it as described above. Otherwise just pass NULL +// to use malloc()/alloca() + +typedef struct +{ + char *alloc_buffer; + int alloc_buffer_length_in_bytes; +} stb_vorbis_alloc; + + +/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES + +typedef struct stb_vorbis stb_vorbis; + +typedef struct +{ + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int setup_temp_memory_required; + unsigned int temp_memory_required; + + int max_frame_size; +} stb_vorbis_info; + +// get general information about the file +extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f); + +// get the last error detected (clears it, too) +extern int stb_vorbis_get_error(stb_vorbis *f); + +// close an ogg vorbis file and free all memory in use +extern void stb_vorbis_close(stb_vorbis *f); + +// this function returns the offset (in samples) from the beginning of the +// file that will be returned by the next decode, if it is known, or -1 +// otherwise. after a flush_pushdata() call, this may take a while before +// it becomes valid again. +// NOT WORKING YET after a seek with PULLDATA API +extern int stb_vorbis_get_sample_offset(stb_vorbis *f); + +// returns the current seek point within the file, or offset from the beginning +// of the memory buffer. In pushdata mode it returns 0. +extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); + +/////////// PUSHDATA API + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +// this API allows you to get blocks of data from any source and hand +// them to stb_vorbis. you have to buffer them; stb_vorbis will tell +// you how much it used, and you have to give it the rest next time; +// and stb_vorbis may not have enough data to work with and you will +// need to give it the same data again PLUS more. Note that the Vorbis +// specification does not bound the size of an individual frame. + +extern stb_vorbis *stb_vorbis_open_pushdata( + unsigned char *datablock, int datablock_length_in_bytes, + int *datablock_memory_consumed_in_bytes, + int *error, + stb_vorbis_alloc *alloc_buffer); +// create a vorbis decoder by passing in the initial data block containing +// the ogg&vorbis headers (you don't need to do parse them, just provide +// the first N bytes of the file--you're told if it's not enough, see below) +// on success, returns an stb_vorbis *, does not set error, returns the amount of +// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; +// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed +// if returns NULL and *error is VORBIS_need_more_data, then the input block was +// incomplete and you need to pass in a larger block from the start of the file + +extern int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes, + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ); +// decode a frame of audio sample data if possible from the passed-in data block +// +// return value: number of bytes we used from datablock +// +// possible cases: +// 0 bytes used, 0 samples output (need more data) +// N bytes used, 0 samples output (resynching the stream, keep going) +// N bytes used, M samples output (one frame of data) +// note that after opening a file, you will ALWAYS get one N-bytes,0-sample +// frame, because Vorbis always "discards" the first frame. +// +// Note that on resynch, stb_vorbis will rarely consume all of the buffer, +// instead only datablock_length_in_bytes-3 or less. This is because it wants +// to avoid missing parts of a page header if they cross a datablock boundary, +// without writing state-machiney code to record a partial detection. +// +// The number of channels returned are stored in *channels (which can be +// NULL--it is always the same as the number of channels reported by +// get_info). *output will contain an array of float* buffers, one per +// channel. In other words, (*output)[0][0] contains the first sample from +// the first channel, and (*output)[1][0] contains the first sample from +// the second channel. + +extern void stb_vorbis_flush_pushdata(stb_vorbis *f); +// inform stb_vorbis that your next datablock will not be contiguous with +// previous ones (e.g. you've seeked in the data); future attempts to decode +// frames will cause stb_vorbis to resynchronize (as noted above), and +// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it +// will begin decoding the _next_ frame. +// +// if you want to seek using pushdata, you need to seek in your file, then +// call stb_vorbis_flush_pushdata(), then start calling decoding, then once +// decoding is returning you data, call stb_vorbis_get_sample_offset, and +// if you don't like the result, seek your file again and repeat. +#endif + + +////////// PULLING INPUT API + +#ifndef STB_VORBIS_NO_PULLDATA_API +// This API assumes stb_vorbis is allowed to pull data from a source-- +// either a block of memory containing the _entire_ vorbis stream, or a +// FILE * that you or it create, or possibly some other reading mechanism +// if you go modify the source to replace the FILE * case with some kind +// of callback to your code. (But if you don't support seeking, you may +// just want to go ahead and use pushdata.) + +#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION) +extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output); +#endif +#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION) +extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output); +#endif +// decode an entire file and output the data interleaved into a malloc()ed +// buffer stored in *output. The return value is the number of samples +// decoded, or -1 if the file could not be opened or was not an ogg vorbis file. +// When you're done with it, just free() the pointer returned in *output. + +extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, + int *error, stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an ogg vorbis stream in memory (note +// this must be the entire stream!). on failure, returns NULL and sets *error + +#ifndef STB_VORBIS_NO_STDIO +extern stb_vorbis * stb_vorbis_open_filename(const char *filename, + int *error, stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from a filename via fopen(). on failure, +// returns NULL and sets *error (possibly to VORBIS_file_open_failure). + +extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, + int *error, stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell). on failure, returns NULL and sets *error. +// note that stb_vorbis must "own" this stream; if you seek it in between +// calls to stb_vorbis, it will become confused. Morever, if you attempt to +// perform stb_vorbis_seek_*() operations on this file, it will assume it +// owns the _entire_ rest of the file after the start point. Use the next +// function, stb_vorbis_open_file_section(), to limit it. + +extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, + int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell); the stream will be of length 'len' bytes. +// on failure, returns NULL and sets *error. note that stb_vorbis must "own" +// this stream; if you seek it in between calls to stb_vorbis, it will become +// confused. +#endif + +extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); +extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); +// NOT WORKING YET +// these functions seek in the Vorbis file to (approximately) 'sample_number'. +// after calling seek_frame(), the next call to get_frame_*() will include +// the specified sample. after calling stb_vorbis_seek(), the next call to +// stb_vorbis_get_samples_* will start with the specified sample. If you +// do not need to seek to EXACTLY the target sample when using get_samples_*, +// you can also use seek_frame(). + +extern void stb_vorbis_seek_start(stb_vorbis *f); +// this function is equivalent to stb_vorbis_seek(f,0), but it +// actually works + +extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); +extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); +// these functions return the total length of the vorbis stream + +extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output); +// decode the next frame and return the number of samples. the number of +// channels returned are stored in *channels (which can be NULL--it is always +// the same as the number of channels reported by get_info). *output will +// contain an array of float* buffers, one per channel. These outputs will +// be overwritten on the next call to stb_vorbis_get_frame_*. +// +// You generally should not intermix calls to stb_vorbis_get_frame_*() +// and stb_vorbis_get_samples_*(), since the latter calls the former. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); +extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); +#endif +// decode the next frame and return the number of samples per channel. the +// data is coerced to the number of channels you request according to the +// channel coercion rules (see below). You must pass in the size of your +// buffer(s) so that stb_vorbis will not overwrite the end of the buffer. +// The maximum buffer size needed can be gotten from get_info(); however, +// the Vorbis I specification implies an absolute maximum of 4096 samples +// per channel. Note that for interleaved data, you pass in the number of +// shorts (the size of your array), but the return value is the number of +// samples per channel, not the total number of samples. + +// Channel coercion rules: +// Let M be the number of channels requested, and N the number of channels present, +// and Cn be the nth channel; let stereo L be the sum of all L and center channels, +// and stereo R be the sum of all R and center channels (channel assignment from the +// vorbis spec). +// M N output +// 1 k sum(Ck) for all k +// 2 * stereo L, stereo R +// k l k > l, the first l channels, then 0s +// k l k <= l, the first k channels +// Note that this is not _good_ surround etc. mixing at all! It's just so +// you get something useful. + +extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats); +extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples); +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. +// Returns the number of samples stored per channel; it may be less than requested +// at the end of the file. If there are no more samples in the file, returns 0. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts); +extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples); +#endif +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. Applies the coercion rules above +// to produce 'channels' channels. Returns the number of samples stored per channel; +// it may be less than requested at the end of the file. If there are no more +// samples in the file, returns 0. + +#endif + +//////// ERROR CODES + +enum STBVorbisError +{ + VORBIS__no_error, + + VORBIS_need_more_data=1, // not a real error + + VORBIS_invalid_api_mixing, // can't mix API modes + VORBIS_outofmem, // not enough memory + VORBIS_feature_not_supported, // uses floor 0 + VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small + VORBIS_file_open_failure, // fopen() failed + VORBIS_seek_without_length, // can't seek in unknown-length file + + VORBIS_unexpected_eof=10, // file is truncated? + VORBIS_seek_invalid, // seek past EOF + + // decoding errors (corrupt/invalid stream) -- you probably + // don't care about the exact details of these + + // vorbis errors: + VORBIS_invalid_setup=20, + VORBIS_invalid_stream, + + // ogg errors: + VORBIS_missing_capture_pattern=30, + VORBIS_invalid_stream_structure_version, + VORBIS_continued_packet_flag_invalid, + VORBIS_incorrect_stream_serial_number, + VORBIS_invalid_first_page, + VORBIS_bad_packet_type, + VORBIS_cant_find_last_page, + VORBIS_seek_failed, +}; + + +#ifdef __cplusplus +} +#endif + +#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H +// +// HEADER ENDS HERE +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef STB_VORBIS_HEADER_ONLY + +// global configuration settings (e.g. set these in the project/makefile), +// or just set them in this file at the top (although ideally the first few +// should be visible when the header file is compiled too, although it's not +// crucial) + +// STB_VORBIS_NO_PUSHDATA_API +// does not compile the code for the various stb_vorbis_*_pushdata() +// functions +// #define STB_VORBIS_NO_PUSHDATA_API + +// STB_VORBIS_NO_PULLDATA_API +// does not compile the code for the non-pushdata APIs +// #define STB_VORBIS_NO_PULLDATA_API + +// STB_VORBIS_NO_STDIO +// does not compile the code for the APIs that use FILE *s internally +// or externally (implied by STB_VORBIS_NO_PULLDATA_API) +// #define STB_VORBIS_NO_STDIO + +// STB_VORBIS_NO_INTEGER_CONVERSION +// does not compile the code for converting audio sample data from +// float to integer (implied by STB_VORBIS_NO_PULLDATA_API) +// #define STB_VORBIS_NO_INTEGER_CONVERSION + +// STB_VORBIS_NO_FAST_SCALED_FLOAT +// does not use a fast float-to-int trick to accelerate float-to-int on +// most platforms which requires endianness be defined correctly. +//#define STB_VORBIS_NO_FAST_SCALED_FLOAT + + +// STB_VORBIS_MAX_CHANNELS [number] +// globally define this to the maximum number of channels you need. +// The spec does not put a restriction on channels except that +// the count is stored in a byte, so 255 is the hard limit. +// Reducing this saves about 16 bytes per value, so using 16 saves +// (255-16)*16 or around 4KB. Plus anything other memory usage +// I forgot to account for. Can probably go as low as 8 (7.1 audio), +// 6 (5.1 audio), or 2 (stereo only). +#ifndef STB_VORBIS_MAX_CHANNELS +#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone? +#endif + +// STB_VORBIS_PUSHDATA_CRC_COUNT [number] +// after a flush_pushdata(), stb_vorbis begins scanning for the +// next valid page, without backtracking. when it finds something +// that looks like a page, it streams through it and verifies its +// CRC32. Should that validation fail, it keeps scanning. But it's +// possible that _while_ streaming through to check the CRC32 of +// one candidate page, it sees another candidate page. This #define +// determines how many "overlapping" candidate pages it can search +// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas +// garbage pages could be as big as 64KB, but probably average ~16KB. +// So don't hose ourselves by scanning an apparent 64KB page and +// missing a ton of real ones in the interim; so minimum of 2 +#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT +#define STB_VORBIS_PUSHDATA_CRC_COUNT 4 +#endif + +// STB_VORBIS_FAST_HUFFMAN_LENGTH [number] +// sets the log size of the huffman-acceleration table. Maximum +// supported value is 24. with larger numbers, more decodings are O(1), +// but the table size is larger so worse cache missing, so you'll have +// to probe (and try multiple ogg vorbis files) to find the sweet spot. +#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH +#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10 +#endif + +// STB_VORBIS_FAST_BINARY_LENGTH [number] +// sets the log size of the binary-search acceleration table. this +// is used in similar fashion to the fast-huffman size to set initial +// parameters for the binary search + +// STB_VORBIS_FAST_HUFFMAN_INT +// The fast huffman tables are much more efficient if they can be +// stored as 16-bit results instead of 32-bit results. This restricts +// the codebooks to having only 65535 possible outcomes, though. +// (At least, accelerated by the huffman table.) +#ifndef STB_VORBIS_FAST_HUFFMAN_INT +#define STB_VORBIS_FAST_HUFFMAN_SHORT +#endif + +// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH +// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls +// back on binary searching for the correct one. This requires storing +// extra tables with the huffman codes in sorted order. Defining this +// symbol trades off space for speed by forcing a linear search in the +// non-fast case, except for "sparse" codebooks. +// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + +// STB_VORBIS_DIVIDES_IN_RESIDUE +// stb_vorbis precomputes the result of the scalar residue decoding +// that would otherwise require a divide per chunk. you can trade off +// space for time by defining this symbol. +// #define STB_VORBIS_DIVIDES_IN_RESIDUE + +// STB_VORBIS_DIVIDES_IN_CODEBOOK +// vorbis VQ codebooks can be encoded two ways: with every case explicitly +// stored, or with all elements being chosen from a small range of values, +// and all values possible in all elements. By default, stb_vorbis expands +// this latter kind out to look like the former kind for ease of decoding, +// because otherwise an integer divide-per-vector-element is required to +// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can +// trade off storage for speed. +//#define STB_VORBIS_DIVIDES_IN_CODEBOOK + +// STB_VORBIS_CODEBOOK_SHORTS +// The vorbis file format encodes VQ codebook floats as ax+b where a and +// b are floating point per-codebook constants, and x is a 16-bit int. +// Normally, stb_vorbis decodes them to floats rather than leaving them +// as 16-bit ints and computing ax+b while decoding. This is a speed/space +// tradeoff; you can save space by defining this flag. +#ifndef STB_VORBIS_CODEBOOK_SHORTS +#define STB_VORBIS_CODEBOOK_FLOATS +#endif + +// STB_VORBIS_DIVIDE_TABLE +// this replaces small integer divides in the floor decode loop with +// table lookups. made less than 1% difference, so disabled by default. + +// STB_VORBIS_NO_INLINE_DECODE +// disables the inlining of the scalar codebook fast-huffman decode. +// might save a little codespace; useful for debugging +// #define STB_VORBIS_NO_INLINE_DECODE + +// STB_VORBIS_NO_DEFER_FLOOR +// Normally we only decode the floor without synthesizing the actual +// full curve. We can instead synthesize the curve immediately. This +// requires more memory and is very likely slower, so I don't think +// you'd ever want to do it except for debugging. +// #define STB_VORBIS_NO_DEFER_FLOOR + + + + +////////////////////////////////////////////////////////////////////////////// + +#ifdef STB_VORBIS_NO_PULLDATA_API + #define STB_VORBIS_NO_INTEGER_CONVERSION + #define STB_VORBIS_NO_STDIO +#endif + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) + #define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + + // only need endianness for fast-float-to-int, which we don't + // use for pushdata + + #ifndef STB_VORBIS_BIG_ENDIAN + #define STB_VORBIS_ENDIAN 0 + #else + #define STB_VORBIS_ENDIAN 1 + #endif + +#endif +#endif + + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifndef STB_VORBIS_NO_CRT +#include +#include +#include +#include +#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) +#include +#endif +#else +#define NULL 0 +#endif + +#if !defined(_MSC_VER) && !(defined(__MINGW32__) && defined(__forceinline)) + #if __GNUC__ + #define __forceinline inline + #else + #define __forceinline + #endif +#endif + +#if STB_VORBIS_MAX_CHANNELS > 256 +#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range" +#endif + +#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24 +#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range" +#endif + + +#define MAX_BLOCKSIZE_LOG 13 // from specification +#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) + + +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifdef STB_VORBIS_CODEBOOK_FLOATS +typedef float codetype; +#else +typedef uint16 codetype; +#endif + +// @NOTE +// +// Some arrays below are tagged "//varies", which means it's actually +// a variable-sized piece of data, but rather than malloc I assume it's +// small enough it's better to just allocate it all together with the +// main thing +// +// Most of the variables are specified with the smallest size I could pack +// them into. It might give better performance to make them all full-sized +// integers. It should be safe to freely rearrange the structures or change +// the sizes larger--nothing relies on silently truncating etc., nor the +// order of variables. + +#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH) +#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1) + +typedef struct +{ + int dimensions, entries; + uint8 *codeword_lengths; + float minimum_value; + float delta_value; + uint8 value_bits; + uint8 lookup_type; + uint8 sequence_p; + uint8 sparse; + uint32 lookup_values; + codetype *multiplicands; + uint32 *codewords; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #else + int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #endif + uint32 *sorted_codewords; + int *sorted_values; + int sorted_entries; +} Codebook; + +typedef struct +{ + uint8 order; + uint16 rate; + uint16 bark_map_size; + uint8 amplitude_bits; + uint8 amplitude_offset; + uint8 number_of_books; + uint8 book_list[16]; // varies +} Floor0; + +typedef struct +{ + uint8 partitions; + uint8 partition_class_list[32]; // varies + uint8 class_dimensions[16]; // varies + uint8 class_subclasses[16]; // varies + uint8 class_masterbooks[16]; // varies + int16 subclass_books[16][8]; // varies + uint16 Xlist[31*8+2]; // varies + uint8 sorted_order[31*8+2]; + uint8 neighbors[31*8+2][2]; + uint8 floor1_multiplier; + uint8 rangebits; + int values; +} Floor1; + +typedef union +{ + Floor0 floor0; + Floor1 floor1; +} Floor; + +typedef struct +{ + uint32 begin, end; + uint32 part_size; + uint8 classifications; + uint8 classbook; + uint8 **classdata; + int16 (*residue_books)[8]; +} Residue; + +typedef struct +{ + uint8 magnitude; + uint8 angle; + uint8 mux; +} MappingChannel; + +typedef struct +{ + uint16 coupling_steps; + MappingChannel *chan; + uint8 submaps; + uint8 submap_floor[15]; // varies + uint8 submap_residue[15]; // varies +} Mapping; + +typedef struct +{ + uint8 blockflag; + uint8 mapping; + uint16 windowtype; + uint16 transformtype; +} Mode; + +typedef struct +{ + uint32 goal_crc; // expected crc if match + int bytes_left; // bytes left in packet + uint32 crc_so_far; // running crc + int bytes_done; // bytes processed in _current_ chunk + uint32 sample_loc; // granule pos encoded in page +} CRCscan; + +typedef struct +{ + uint32 page_start, page_end; + uint32 after_previous_page_start; + uint32 first_decoded_sample; + uint32 last_decoded_sample; +} ProbedPage; + +struct stb_vorbis +{ + // user-accessible info + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int temp_memory_required; + unsigned int setup_temp_memory_required; + + // input config +#ifndef STB_VORBIS_NO_STDIO + FILE *f; + uint32 f_start; + int close_on_free; +#endif + + uint8 *stream; + uint8 *stream_start; + uint8 *stream_end; + + uint32 stream_len; + + uint8 push_mode; + + uint32 first_audio_page_offset; + + ProbedPage p_first, p_last; + + // memory management + stb_vorbis_alloc alloc; + int setup_offset; + int temp_offset; + + // run-time results + int eof; + enum STBVorbisError error; + + // user-useful data + + // header info + int blocksize[2]; + int blocksize_0, blocksize_1; + int codebook_count; + Codebook *codebooks; + int floor_count; + uint16 floor_types[64]; // varies + Floor *floor_config; + int residue_count; + uint16 residue_types[64]; // varies + Residue *residue_config; + int mapping_count; + Mapping *mapping; + int mode_count; + Mode mode_config[64]; // varies + + uint32 total_samples; + + // decode buffer + float *channel_buffers[STB_VORBIS_MAX_CHANNELS]; + float *outputs [STB_VORBIS_MAX_CHANNELS]; + + float *previous_window[STB_VORBIS_MAX_CHANNELS]; + int previous_length; + + #ifndef STB_VORBIS_NO_DEFER_FLOOR + int16 *finalY[STB_VORBIS_MAX_CHANNELS]; + #else + float *floor_buffers[STB_VORBIS_MAX_CHANNELS]; + #endif + + uint32 current_loc; // sample location of next frame to decode + int current_loc_valid; + + // per-blocksize precomputed data + + // twiddle factors + float *A[2],*B[2],*C[2]; + float *window[2]; + uint16 *bit_reverse[2]; + + // current page/packet/segment streaming info + uint32 serial; // stream serial number for verification + int last_page; + int segment_count; + uint8 segments[255]; + uint8 page_flag; + uint8 bytes_in_seg; + uint8 first_decode; + int next_seg; + int last_seg; // flag that we're on the last segment + int last_seg_which; // what was the segment number of the last seg? + uint32 acc; + int valid_bits; + int packet_bytes; + int end_seg_with_known_loc; + uint32 known_loc_for_packet; + int discard_samples_deferred; + uint32 samples_output; + + // push mode scanning + int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching +#ifndef STB_VORBIS_NO_PUSHDATA_API + CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; +#endif + + // sample-access + int channel_buffer_start; + int channel_buffer_end; +}; + +extern int my_prof(int slot); +//#define stb_prof my_prof + +#ifndef stb_prof +#define stb_prof(x) ((void) 0) +#endif + +#if defined(STB_VORBIS_NO_PUSHDATA_API) + #define IS_PUSH_MODE(f) FALSE +#elif defined(STB_VORBIS_NO_PULLDATA_API) + #define IS_PUSH_MODE(f) TRUE +#else + #define IS_PUSH_MODE(f) ((f)->push_mode) +#endif + +typedef struct stb_vorbis vorb; + +static int error(vorb *f, enum STBVorbisError e) +{ + f->error = e; + if (!f->eof && e != VORBIS_need_more_data) { + f->error=e; // breakpoint for debugging + } + return 0; +} + + +// these functions are used for allocating temporary memory +// while decoding. if you can afford the stack space, use +// alloca(); otherwise, provide a temp buffer and it will +// allocate out of those. + +#define array_size_required(count,size) (count*(sizeof(void *)+(size))) + +#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) +#ifdef dealloca +#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size)) +#else +#define temp_free(f,p) 0 +#endif +#define temp_alloc_save(f) ((f)->temp_offset) +#define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) + +#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size) + +// given a sufficiently large block of memory, make an array of pointers to subblocks of it +static void *make_block_array(void *mem, int count, int size) +{ + int i; + void ** p = (void **) mem; + char *q = (char *) (p + count); + for (i=0; i < count; ++i) { + p[i] = q; + q += size; + } + return p; +} + +static void *setup_malloc(vorb *f, int sz) +{ + sz = (sz+3) & ~3; + f->setup_memory_required += sz; + if (f->alloc.alloc_buffer) { + void *p = (char *) f->alloc.alloc_buffer + f->setup_offset; + if (f->setup_offset + sz > f->temp_offset) return NULL; + f->setup_offset += sz; + return p; + } + return sz ? malloc(sz) : NULL; +} + +static void setup_free(vorb *f, void *p) +{ + if (f->alloc.alloc_buffer) return; // do nothing; setup mem is not a stack + free(p); +} + +static void *setup_temp_malloc(vorb *f, int sz) +{ + sz = (sz+3) & ~3; + if (f->alloc.alloc_buffer) { + if (f->temp_offset - sz < f->setup_offset) return NULL; + f->temp_offset -= sz; + return (char *) f->alloc.alloc_buffer + f->temp_offset; + } + return malloc(sz); +} + +static void setup_temp_free(vorb *f, void *p, int sz) +{ + if (f->alloc.alloc_buffer) { + f->temp_offset += (sz+3)&~3; + return; + } + free(p); +} + +#define CRC32_POLY 0x04c11db7 // from spec + +static uint32 crc_table[256]; +static void crc32_init(void) +{ + int i,j; + uint32 s; + for(i=0; i < 256; i++) { + for (s=i<<24, j=0; j < 8; ++j) + s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); + crc_table[i] = s; + } +} + +static __forceinline uint32 crc32_update(uint32 crc, uint8 byte) +{ + return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; +} + + +// used in setup, and for huffman that doesn't go fast path +static unsigned int bit_reverse(unsigned int n) +{ + n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); + n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); + n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); + n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); + return (n >> 16) | (n << 16); +} + +static float square(float x) +{ + return x*x; +} + +// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3 +// as required by the specification. fast(?) implementation from stb.h +// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup +static int ilog(int32 n) +{ + static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; + + // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) + if (n < (1 << 14)) + if (n < (1 << 4)) return 0 + log2_4[n ]; + else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; + else return 10 + log2_4[n >> 10]; + else if (n < (1 << 24)) + if (n < (1 << 19)) return 15 + log2_4[n >> 15]; + else return 20 + log2_4[n >> 20]; + else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; + else if (n < (1 << 31)) return 30 + log2_4[n >> 30]; + else return 0; // signed n returns 0 +} + +#ifndef M_PI + #define M_PI 3.14159265358979323846264f // from CRC +#endif + +// code length assigned to a value with no huffman encoding +#define NO_CODE 255 + +/////////////////////// LEAF SETUP FUNCTIONS ////////////////////////// +// +// these functions are only called at setup, and only a few times +// per file + +static float float32_unpack(uint32 x) +{ + // from the specification + uint32 mantissa = x & 0x1fffff; + uint32 sign = x & 0x80000000; + uint32 exp = (x & 0x7fe00000) >> 21; + double res = sign ? -(double)mantissa : (double)mantissa; + return (float) ldexp((float)res, exp-788); +} + + +// zlib & jpeg huffman tables assume that the output symbols +// can either be arbitrarily arranged, or have monotonically +// increasing frequencies--they rely on the lengths being sorted; +// this makes for a very simple generation algorithm. +// vorbis allows a huffman table with non-sorted lengths. This +// requires a more sophisticated construction, since symbols in +// order do not map to huffman codes "in order". +static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values) +{ + if (!c->sparse) { + c->codewords [symbol] = huff_code; + } else { + c->codewords [count] = huff_code; + c->codeword_lengths[count] = len; + values [count] = symbol; + } +} + +static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) +{ + int i,k,m=0; + uint32 available[32]; + + memset(available, 0, sizeof(available)); + // find the first entry + for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; + if (k == n) { assert(c->sorted_entries == 0); return TRUE; } + // add to the list + add_entry(c, 0, k, m++, len[k], values); + // add all available leaves + for (i=1; i <= len[k]; ++i) + available[i] = 1 << (32-i); + // note that the above code treats the first case specially, + // but it's really the same as the following code, so they + // could probably be combined (except the initial code is 0, + // and I use 0 in available[] to mean 'empty') + for (i=k+1; i < n; ++i) { + uint32 res; + int z = len[i], y; + if (z == NO_CODE) continue; + // find lowest available leaf (should always be earliest, + // which is what the specification calls for) + // note that this property, and the fact we can never have + // more than one free leaf at a given level, isn't totally + // trivial to prove, but it seems true and the assert never + // fires, so! + while (z > 0 && !available[z]) --z; + if (z == 0) { assert(0); return FALSE; } + res = available[z]; + available[z] = 0; + add_entry(c, bit_reverse(res), i, m++, len[i], values); + // propogate availability up the tree + if (z != len[i]) { + for (y=len[i]; y > z; --y) { + assert(available[y] == 0); + available[y] = res + (1 << (32-y)); + } + } + } + return TRUE; +} + +// accelerated huffman table allows fast O(1) match of all symbols +// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH +static void compute_accelerated_huffman(Codebook *c) +{ + int i, len; + for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) + c->fast_huffman[i] = -1; + + len = c->sparse ? c->sorted_entries : c->entries; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + if (len > 32767) len = 32767; // largest possible value we can encode! + #endif + for (i=0; i < len; ++i) { + if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) { + uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; + // set table entries for all bit combinations in the higher bits + while (z < FAST_HUFFMAN_TABLE_SIZE) { + c->fast_huffman[z] = i; + z += 1 << c->codeword_lengths[i]; + } + } + } +} + +#ifdef _MSC_VER +#define STBV_CDECL __cdecl +#else +#define STBV_CDECL +#endif + +static int STBV_CDECL uint32_compare(const void *p, const void *q) +{ + uint32 x = * (uint32 *) p; + uint32 y = * (uint32 *) q; + return x < y ? -1 : x > y; +} + +static int include_in_sort(Codebook *c, uint8 len) +{ + if (c->sparse) { assert(len != NO_CODE); return TRUE; } + if (len == NO_CODE) return FALSE; + if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; + return FALSE; +} + +// if the fast table above doesn't work, we want to binary +// search them... need to reverse the bits +static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) +{ + int i, len; + // build a list of all the entries + // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. + // this is kind of a frivolous optimization--I don't see any performance improvement, + // but it's like 4 extra lines of code, so. + if (!c->sparse) { + int k = 0; + for (i=0; i < c->entries; ++i) + if (include_in_sort(c, lengths[i])) + c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); + assert(k == c->sorted_entries); + } else { + for (i=0; i < c->sorted_entries; ++i) + c->sorted_codewords[i] = bit_reverse(c->codewords[i]); + } + + qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); + c->sorted_codewords[c->sorted_entries] = 0xffffffff; + + len = c->sparse ? c->sorted_entries : c->entries; + // now we need to indicate how they correspond; we could either + // #1: sort a different data structure that says who they correspond to + // #2: for each sorted entry, search the original list to find who corresponds + // #3: for each original entry, find the sorted entry + // #1 requires extra storage, #2 is slow, #3 can use binary search! + for (i=0; i < len; ++i) { + int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; + if (include_in_sort(c,huff_len)) { + uint32 code = bit_reverse(c->codewords[i]); + int x=0, n=c->sorted_entries; + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + assert(c->sorted_codewords[x] == code); + if (c->sparse) { + c->sorted_values[x] = values[i]; + c->codeword_lengths[x] = huff_len; + } else { + c->sorted_values[x] = i; + } + } + } +} + +// only run while parsing the header (3 times) +static int vorbis_validate(uint8 *data) +{ + static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' }; + return memcmp(data, vorbis, 6) == 0; +} + +// called from setup only, once per code book +// (formula implied by specification) +static int lookup1_values(int entries, int dim) +{ + int r = (int) floor(exp((float) log((float) entries) / dim)); + if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; + ++r; // floor() to avoid _ftol() when non-CRT + assert(pow((float) r+1, dim) > entries); + assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above + return r; +} + +// called twice per file +static void compute_twiddle_factors(int n, float *A, float *B, float *C) +{ + int n4 = n >> 2, n8 = n >> 3; + int k,k2; + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f; + B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f; + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } +} + +static void compute_window(int n, float *window) +{ + int n2 = n >> 1, i; + for (i=0; i < n2; ++i) + window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); +} + +static void compute_bitreverse(int n, uint16 *rev) +{ + int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + int i, n8 = n >> 3; + for (i=0; i < n8; ++i) + rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2; +} + +static int init_blocksize(vorb *f, int b, int n) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; + f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4); + if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); + compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); + f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2); + if (!f->window[b]) return error(f, VORBIS_outofmem); + compute_window(n, f->window[b]); + f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8); + if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); + compute_bitreverse(n, f->bit_reverse[b]); + return TRUE; +} + +static void neighbors(uint16 *x, int n, int *plow, int *phigh) +{ + int low = -1; + int high = 65536; + int i; + for (i=0; i < n; ++i) { + if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; } + if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; } + } +} + +// this has been repurposed so y is now the original index instead of y +typedef struct +{ + uint16 x,y; +} Point; + +static int STBV_CDECL point_compare(const void *p, const void *q) +{ + Point *a = (Point *) p; + Point *b = (Point *) q; + return a->x < b->x ? -1 : a->x > b->x; +} + +// +/////////////////////// END LEAF SETUP FUNCTIONS ////////////////////////// + + +#if defined(STB_VORBIS_NO_STDIO) + #define USE_MEMORY(z) TRUE +#else + #define USE_MEMORY(z) ((z)->stream) +#endif + +static uint8 get8(vorb *z) +{ + if (USE_MEMORY(z)) { + if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; } + return *z->stream++; + } + + #ifndef STB_VORBIS_NO_STDIO + { + int c = fgetc(z->f); + if (c == EOF) { z->eof = TRUE; return 0; } + return c; + } + #endif +} + +static uint32 get32(vorb *f) +{ + uint32 x; + x = get8(f); + x += get8(f) << 8; + x += get8(f) << 16; + x += get8(f) << 24; + return x; +} + +static int getn(vorb *z, uint8 *data, int n) +{ + if (USE_MEMORY(z)) { + if (z->stream+n > z->stream_end) { z->eof = 1; return 0; } + memcpy(data, z->stream, n); + z->stream += n; + return 1; + } + + #ifndef STB_VORBIS_NO_STDIO + if (fread(data, n, 1, z->f) == 1) + return 1; + else { + z->eof = 1; + return 0; + } + #endif +} + +static void skip(vorb *z, int n) +{ + if (USE_MEMORY(z)) { + z->stream += n; + if (z->stream >= z->stream_end) z->eof = 1; + return; + } + #ifndef STB_VORBIS_NO_STDIO + { + long x = ftell(z->f); + fseek(z->f, x+n, SEEK_SET); + } + #endif +} + +static int set_file_offset(stb_vorbis *f, unsigned int loc) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + f->eof = 0; + if (USE_MEMORY(f)) { + if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { + f->stream = f->stream_end; + f->eof = 1; + return 0; + } else { + f->stream = f->stream_start + loc; + return 1; + } + } + #ifndef STB_VORBIS_NO_STDIO + if (loc + f->f_start < loc || loc >= 0x80000000) { + loc = 0x7fffffff; + f->eof = 1; + } else { + loc += f->f_start; + } + if (!fseek(f->f, loc, SEEK_SET)) + return 1; + f->eof = 1; + fseek(f->f, f->f_start, SEEK_END); + return 0; + #endif +} + + +static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 }; + +static int capture_pattern(vorb *f) +{ + if (0x4f != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x53 != get8(f)) return FALSE; + return TRUE; +} + +#define PAGEFLAG_continued_packet 1 +#define PAGEFLAG_first_page 2 +#define PAGEFLAG_last_page 4 + +static int start_page_no_capturepattern(vorb *f) +{ + uint32 loc0,loc1,n; + // stream structure version + if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); + // header flag + f->page_flag = get8(f); + // absolute granule position + loc0 = get32(f); + loc1 = get32(f); + // @TODO: validate loc0,loc1 as valid positions? + // stream serial number -- vorbis doesn't interleave, so discard + get32(f); + //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); + // page sequence number + n = get32(f); + f->last_page = n; + // CRC32 + get32(f); + // page_segments + f->segment_count = get8(f); + if (!getn(f, f->segments, f->segment_count)) + return error(f, VORBIS_unexpected_eof); + // assume we _don't_ know any the sample position of any segments + f->end_seg_with_known_loc = -2; + if (loc0 != ~0U || loc1 != ~0U) { + int i; + // determine which packet is the last one that will complete + for (i=f->segment_count-1; i >= 0; --i) + if (f->segments[i] < 255) + break; + // 'i' is now the index of the _last_ segment of a packet that ends + if (i >= 0) { + f->end_seg_with_known_loc = i; + f->known_loc_for_packet = loc0; + } + } + if (f->first_decode) { + int i,len; + ProbedPage p; + len = 0; + for (i=0; i < f->segment_count; ++i) + len += f->segments[i]; + len += 27 + f->segment_count; + p.page_start = f->first_audio_page_offset; + p.page_end = p.page_start + len; + p.after_previous_page_start = p.page_start; + p.first_decoded_sample = 0; + p.last_decoded_sample = loc0; + f->p_first = p; + } + f->next_seg = 0; + return TRUE; +} + +static int start_page(vorb *f) +{ + if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); + return start_page_no_capturepattern(f); +} + +static int start_packet(vorb *f) +{ + while (f->next_seg == -1) { + if (!start_page(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) + return error(f, VORBIS_continued_packet_flag_invalid); + } + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + // f->next_seg is now valid + return TRUE; +} + +static int maybe_start_packet(vorb *f) +{ + if (f->next_seg == -1) { + int x = get8(f); + if (f->eof) return FALSE; // EOF at page boundary is not an error! + if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (!start_page_no_capturepattern(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) { + // set up enough state that we can read this packet if we want, + // e.g. during recovery + f->last_seg = FALSE; + f->bytes_in_seg = 0; + return error(f, VORBIS_continued_packet_flag_invalid); + } + } + return start_packet(f); +} + +static int next_segment(vorb *f) +{ + int len; + if (f->last_seg) return 0; + if (f->next_seg == -1) { + f->last_seg_which = f->segment_count-1; // in case start_page fails + if (!start_page(f)) { f->last_seg = 1; return 0; } + if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); + } + len = f->segments[f->next_seg++]; + if (len < 255) { + f->last_seg = TRUE; + f->last_seg_which = f->next_seg-1; + } + if (f->next_seg >= f->segment_count) + f->next_seg = -1; + assert(f->bytes_in_seg == 0); + f->bytes_in_seg = len; + return len; +} + +#define EOP (-1) +#define INVALID_BITS (-1) + +static int get8_packet_raw(vorb *f) +{ + if (!f->bytes_in_seg) { // CLANG! + if (f->last_seg) return EOP; + else if (!next_segment(f)) return EOP; + } + assert(f->bytes_in_seg > 0); + --f->bytes_in_seg; + ++f->packet_bytes; + return get8(f); +} + +static int get8_packet(vorb *f) +{ + int x = get8_packet_raw(f); + f->valid_bits = 0; + return x; +} + +static void flush_packet(vorb *f) +{ + while (get8_packet_raw(f) != EOP); +} + +// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important +// as the huffman decoder? +static uint32 get_bits(vorb *f, int n) +{ + uint32 z; + + if (f->valid_bits < 0) return 0; + if (f->valid_bits < n) { + if (n > 24) { + // the accumulator technique below would not work correctly in this case + z = get_bits(f, 24); + z += get_bits(f, n-24) << 24; + return z; + } + if (f->valid_bits == 0) f->acc = 0; + while (f->valid_bits < n) { + int z = get8_packet_raw(f); + if (z == EOP) { + f->valid_bits = INVALID_BITS; + return 0; + } + f->acc += z << f->valid_bits; + f->valid_bits += 8; + } + } + if (f->valid_bits < 0) return 0; + z = f->acc & ((1 << n)-1); + f->acc >>= n; + f->valid_bits -= n; + return z; +} + +// @OPTIMIZE: primary accumulator for huffman +// expand the buffer to as many bits as possible without reading off end of packet +// it might be nice to allow f->valid_bits and f->acc to be stored in registers, +// e.g. cache them locally and decode locally +static __forceinline void prep_huffman(vorb *f) +{ + if (f->valid_bits <= 24) { + if (f->valid_bits == 0) f->acc = 0; + do { + int z; + if (f->last_seg && !f->bytes_in_seg) return; + z = get8_packet_raw(f); + if (z == EOP) return; + f->acc += z << f->valid_bits; + f->valid_bits += 8; + } while (f->valid_bits <= 24); + } +} + +enum +{ + VORBIS_packet_id = 1, + VORBIS_packet_comment = 3, + VORBIS_packet_setup = 5, +}; + +static int codebook_decode_scalar_raw(vorb *f, Codebook *c) +{ + int i; + prep_huffman(f); + + assert(c->sorted_codewords || c->codewords); + // cases to use binary search: sorted_codewords && !c->codewords + // sorted_codewords && c->entries > 8 + if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { + // binary search + uint32 code = bit_reverse(f->acc); + int x=0, n=c->sorted_entries, len; + + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + // x is now the sorted index + if (!c->sparse) x = c->sorted_values[x]; + // x is now sorted index if sparse, or symbol otherwise + len = c->codeword_lengths[x]; + if (f->valid_bits >= len) { + f->acc >>= len; + f->valid_bits -= len; + return x; + } + + f->valid_bits = 0; + return -1; + } + + // if small, linear search + assert(!c->sparse); + for (i=0; i < c->entries; ++i) { + if (c->codeword_lengths[i] == NO_CODE) continue; + if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) { + if (f->valid_bits >= c->codeword_lengths[i]) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + return i; + } + f->valid_bits = 0; + return -1; + } + } + + error(f, VORBIS_invalid_stream); + f->valid_bits = 0; + return -1; +} + +#ifndef STB_VORBIS_NO_INLINE_DECODE + +#define DECODE_RAW(var, f,c) \ + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) \ + prep_huffman(f); \ + var = f->acc & FAST_HUFFMAN_TABLE_MASK; \ + var = c->fast_huffman[var]; \ + if (var >= 0) { \ + int n = c->codeword_lengths[var]; \ + f->acc >>= n; \ + f->valid_bits -= n; \ + if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \ + } else { \ + var = codebook_decode_scalar_raw(f,c); \ + } + +#else + +static int codebook_decode_scalar(vorb *f, Codebook *c) +{ + int i; + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) + prep_huffman(f); + // fast huffman table lookup + i = f->acc & FAST_HUFFMAN_TABLE_MASK; + i = c->fast_huffman[i]; + if (i >= 0) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + if (f->valid_bits < 0) { f->valid_bits = 0; return -1; } + return i; + } + return codebook_decode_scalar_raw(f,c); +} + +#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c); + +#endif + +#define DECODE(var,f,c) \ + DECODE_RAW(var,f,c) \ + if (c->sparse) var = c->sorted_values[var]; + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) +#else + #define DECODE_VQ(var,f,c) DECODE(var,f,c) +#endif + + + + + + +// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case +// where we avoid one addition +#ifndef STB_VORBIS_CODEBOOK_FLOATS + #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value) + #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value) + #define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value) +#else + #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) + #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) + #define CODEBOOK_ELEMENT_BASE(c) (0) +#endif + +static int codebook_decode_start(vorb *f, Codebook *c) +{ + int z = -1; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) + error(f, VORBIS_invalid_stream); + else { + DECODE_VQ(z,f,c); + if (c->sparse) assert(z < c->sorted_entries); + if (z < 0) { // check for EOP + if (!f->bytes_in_seg) + if (f->last_seg) + return z; + error(f, VORBIS_invalid_stream); + } + } + return z; +} + +static int codebook_decode(vorb *f, Codebook *c, float *output, int len) +{ + int i,z = codebook_decode_start(f,c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + float last = CODEBOOK_ELEMENT_BASE(c); + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i] += val; + if (c->sequence_p) last = val + c->minimum_value; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + if (c->sequence_p) { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i] += val; + last = val + c->minimum_value; + } + } else { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; + } + } + + return TRUE; +} + +static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step) +{ + int i,z = codebook_decode_start(f,c); + float last = CODEBOOK_ELEMENT_BASE(c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + } + + return TRUE; +} + +static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode) +{ + int c_inter = *c_inter_p; + int p_inter = *p_inter_p; + int i,z, effective = c->dimensions; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); + + while (total_decode > 0) { + float last = CODEBOOK_ELEMENT_BASE(c); + DECODE_VQ(z,f,c); + #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + assert(!c->sparse || z < c->sorted_entries); + #endif + if (z < 0) { + if (!f->bytes_in_seg) + if (f->last_seg) return FALSE; + return error(f, VORBIS_invalid_stream); + } + + // if this will take us off the end of the buffers, stop short! + // we check by computing the length of the virtual interleaved + // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), + // and the length we'll be using (effective) + if (c_inter + p_inter*ch + effective > len * ch) { + effective = len*ch - (p_inter*ch - c_inter); + } + + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < effective; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + } else + #endif + { + z *= c->dimensions; + if (c->sequence_p) { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + last = val; + } + } else { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + } + } + } + + total_decode -= effective; + } + *c_inter_p = c_inter; + *p_inter_p = p_inter; + return TRUE; +} + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK +static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **outputs, int *c_inter_p, int *p_inter_p, int len, int total_decode) +{ + int c_inter = *c_inter_p; + int p_inter = *p_inter_p; + int i,z, effective = c->dimensions; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); + + while (total_decode > 0) { + float last = CODEBOOK_ELEMENT_BASE(c); + DECODE_VQ(z,f,c); + + if (z < 0) { + if (!f->bytes_in_seg) + if (f->last_seg) return FALSE; + return error(f, VORBIS_invalid_stream); + } + + // if this will take us off the end of the buffers, stop short! + // we check by computing the length of the virtual interleaved + // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), + // and the length we'll be using (effective) + if (c_inter + p_inter*2 + effective > len * 2) { + effective = len*2 - (p_inter*2 - c_inter); + } + + { + z *= c->dimensions; + stb_prof(11); + if (c->sequence_p) { + // haven't optimized this case because I don't have any examples + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == 2) { c_inter = 0; ++p_inter; } + last = val; + } + } else { + i=0; + if (c_inter == 1) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + c_inter = 0; ++p_inter; + ++i; + } + { + float *z0 = outputs[0]; + float *z1 = outputs[1]; + for (; i+1 < effective;) { + float v0 = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + float v1 = CODEBOOK_ELEMENT_FAST(c,z+i+1) + last; + if (z0) + z0[p_inter] += v0; + if (z1) + z1[p_inter] += v1; + ++p_inter; + i += 2; + } + } + if (i < effective) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + if (outputs[c_inter]) + outputs[c_inter][p_inter] += val; + if (++c_inter == 2) { c_inter = 0; ++p_inter; } + } + } + } + + total_decode -= effective; + } + *c_inter_p = c_inter; + *p_inter_p = p_inter; + return TRUE; +} +#endif + +static int predict_point(int x, int x0, int x1, int y0, int y1) +{ + int dy = y1 - y0; + int adx = x1 - x0; + // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? + int err = abs(dy) * (x - x0); + int off = err / adx; + return dy < 0 ? y0 - off : y0 + off; +} + +// the following table is block-copied from the specification +static float inverse_db_table[256] = +{ + 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, + 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, + 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, + 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, + 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, + 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, + 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, + 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, + 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, + 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, + 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, + 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, + 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, + 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, + 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, + 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, + 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, + 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, + 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, + 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, + 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, + 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, + 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, + 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, + 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, + 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, + 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, + 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, + 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, + 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, + 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, + 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, + 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, + 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, + 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, + 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, + 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, + 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, + 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, + 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, + 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, + 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, + 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, + 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, + 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, + 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, + 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, + 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, + 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, + 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, + 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, + 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, + 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, + 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, + 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, + 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, + 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, + 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, + 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, + 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, + 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, + 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, + 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, + 0.82788260f, 0.88168307f, 0.9389798f, 1.0f +}; + + +// @OPTIMIZE: if you want to replace this bresenham line-drawing routine, +// note that you must produce bit-identical output to decode correctly; +// this specific sequence of operations is specified in the spec (it's +// drawing integer-quantized frequency-space lines that the encoder +// expects to be exactly the same) +// ... also, isn't the whole point of Bresenham's algorithm to NOT +// have to divide in the setup? sigh. +#ifndef STB_VORBIS_NO_DEFER_FLOOR +#define LINE_OP(a,b) a *= b +#else +#define LINE_OP(a,b) a = b +#endif + +#ifdef STB_VORBIS_DIVIDE_TABLE +#define DIVTAB_NUMER 32 +#define DIVTAB_DENOM 64 +int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB +#endif + +static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n) +{ + int dy = y1 - y0; + int adx = x1 - x0; + int ady = abs(dy); + int base; + int x=x0,y=y0; + int err = 0; + int sy; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) { + if (dy < 0) { + base = -integer_divide_table[ady][adx]; + sy = base-1; + } else { + base = integer_divide_table[ady][adx]; + sy = base+1; + } + } else { + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; + } +#else + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; +#endif + ady -= abs(base) * adx; + if (x1 > n) x1 = n; + LINE_OP(output[x], inverse_db_table[y]); + for (++x; x < x1; ++x) { + err += ady; + if (err >= adx) { + err -= adx; + y += sy; + } else + y += base; + LINE_OP(output[x], inverse_db_table[y]); + } +} + +static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype) +{ + int k; + if (rtype == 0) { + int step = n / book->dimensions; + for (k=0; k < step; ++k) + if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step)) + return FALSE; + } else { + for (k=0; k < n; ) { + if (!codebook_decode(f, book, target+offset, n-k)) + return FALSE; + k += book->dimensions; + offset += book->dimensions; + } + } + return TRUE; +} + +static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) +{ + int i,j,pass; + Residue *r = f->residue_config + rn; + int rtype = f->residue_types[rn]; + int c = r->classbook; + int classwords = f->codebooks[c].dimensions; + int n_read = r->end - r->begin; + int part_read = n_read / r->part_size; + int temp_alloc_point = temp_alloc_save(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata)); + #else + int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); + #endif + + stb_prof(2); + for (i=0; i < ch; ++i) + if (!do_not_decode[i]) + memset(residue_buffers[i], 0, sizeof(float) * n); + + if (rtype == 2 && ch != 1) { + for (j=0; j < ch; ++j) + if (!do_not_decode[j]) + break; + if (j == ch) + goto done; + + stb_prof(3); + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set = 0; + if (ch == 2) { + stb_prof(13); + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = (z & 1), p_inter = z>>1; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + stb_prof(5); + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + stb_prof(20); // accounts for X time + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + #else + // saves 1% + if (!codebook_decode_deinterleave_repeat_2(f, book, residue_buffers, &c_inter, &p_inter, n, r->part_size)) + goto done; + #endif + stb_prof(7); + } else { + z += r->part_size; + c_inter = z & 1; + p_inter = z >> 1; + } + } + stb_prof(8); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } else if (ch == 1) { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = 0, p_inter = z; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + stb_prof(22); + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + stb_prof(3); + } else { + z += r->part_size; + c_inter = 0; + p_inter = z; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } else { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = z % ch, p_inter = z/ch; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + stb_prof(22); + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + stb_prof(3); + } else { + z += r->part_size; + c_inter = z % ch; + p_inter = z / ch; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + } + goto done; + } + stb_prof(9); + + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set=0; + while (pcount < part_read) { + if (pass == 0) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + Codebook *c = f->codebooks+r->classbook; + int temp; + DECODE(temp,f,c); + if (temp == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[j][class_set] = r->classdata[temp]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[j][i+pcount] = temp % r->classifications; + temp /= r->classifications; + } + #endif + } + } + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[j][class_set][i]; + #else + int c = classifications[j][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + float *target = residue_buffers[j]; + int offset = r->begin + pcount * r->part_size; + int n = r->part_size; + Codebook *book = f->codebooks + b; + if (!residue_decode(f, book, target, offset, n, rtype)) + goto done; + } + } + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + done: + stb_prof(0); + temp_alloc_restore(f,temp_alloc_point); +} + + +#if 0 +// slow way for debugging +void inverse_mdct_slow(float *buffer, int n) +{ + int i,j; + int n2 = n >> 1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + // formula from paper: + //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + // formula from wikipedia + //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + // these are equivalent, except the formula from the paper inverts the multiplier! + // however, what actually works is NO MULTIPLIER!?! + //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + buffer[i] = acc; + } + free(x); +} +#elif 0 +// same as above, but just barely able to run in real time on modern machines +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + float mcos[16384]; + int i,j; + int n2 = n >> 1, nmask = (n << 2) -1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < 4*n; ++i) + mcos[i] = (float) cos(M_PI / 2 * i / n); + + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask]; + buffer[i] = acc; + } + free(x); +} +#elif 0 +// transform to use a slow dct-iv; this is STILL basically trivial, +// but only requires half as many ops +void dct_iv_slow(float *buffer, int n) +{ + float mcos[16384]; + float x[2048]; + int i,j; + int n2 = n >> 1, nmask = (n << 3) - 1; + memcpy(x, buffer, sizeof(*x) * n); + for (i=0; i < 8*n; ++i) + mcos[i] = (float) cos(M_PI / 4 * i / n); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n; ++j) + acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask]; + buffer[i] = acc; + } +} + +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4; + float temp[4096]; + + memcpy(temp, buffer, n2 * sizeof(float)); + dct_iv_slow(temp, n2); // returns -c'-d, a-b' + + for (i=0; i < n4 ; ++i) buffer[i] = temp[i+n4]; // a-b' + for ( ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1]; // b-a', c+d' + for ( ; i < n ; ++i) buffer[i] = -temp[i - n3_4]; // c'+d +} +#endif + +#ifndef LIBVORBIS_MDCT +#define LIBVORBIS_MDCT 0 +#endif + +#if LIBVORBIS_MDCT +// directly call the vorbis MDCT using an interface documented +// by Jeff Roberts... useful for performance comparison +typedef struct +{ + int n; + int log2n; + + float *trig; + int *bitrev; + + float scale; +} mdct_lookup; + +extern void mdct_init(mdct_lookup *lookup, int n); +extern void mdct_clear(mdct_lookup *l); +extern void mdct_backward(mdct_lookup *init, float *in, float *out); + +mdct_lookup M1,M2; + +void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + mdct_lookup *M; + if (M1.n == n) M = &M1; + else if (M2.n == n) M = &M2; + else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } + else { + if (M2.n) __asm int 3; + mdct_init(&M2, n); + M = &M2; + } + + mdct_backward(M, buffer, buffer); +} +#endif + + +// the following were split out into separate functions while optimizing; +// they could be pushed back up but eh. __forceinline showed no change; +// they're probably already being inlined. +static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A) +{ + float *ee0 = e + i_off; + float *ee2 = ee0 + k_off; + int i; + + assert((n & 3) == 0); + for (i=(n>>2); i > 0; --i) { + float k00_20, k01_21; + k00_20 = ee0[ 0] - ee2[ 0]; + k01_21 = ee0[-1] - ee2[-1]; + ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-2] - ee2[-2]; + k01_21 = ee0[-3] - ee2[-3]; + ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-4] - ee2[-4]; + k01_21 = ee0[-5] - ee2[-5]; + ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-6] - ee2[-6]; + k01_21 = ee0[-7] - ee2[-7]; + ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + ee0 -= 8; + ee2 -= 8; + } +} + +static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1) +{ + int i; + float k00_20, k01_21; + + float *e0 = e + d0; + float *e2 = e0 + k_off; + + for (i=lim >> 2; i > 0; --i) { + k00_20 = e0[-0] - e2[-0]; + k01_21 = e0[-1] - e2[-1]; + e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0]; + e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1]; + e2[-0] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-1] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-2] - e2[-2]; + k01_21 = e0[-3] - e2[-3]; + e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2]; + e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3]; + e2[-2] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-3] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-4] - e2[-4]; + k01_21 = e0[-5] - e2[-5]; + e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4]; + e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5]; + e2[-4] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-5] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-6] - e2[-6]; + k01_21 = e0[-7] - e2[-7]; + e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6]; + e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7]; + e2[-6] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-7] = (k01_21)*A[0] + (k00_20) * A[1]; + + e0 -= 8; + e2 -= 8; + + A += k1; + } +} + +static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0) +{ + int i; + float A0 = A[0]; + float A1 = A[0+1]; + float A2 = A[0+a_off]; + float A3 = A[0+a_off+1]; + float A4 = A[0+a_off*2+0]; + float A5 = A[0+a_off*2+1]; + float A6 = A[0+a_off*3+0]; + float A7 = A[0+a_off*3+1]; + + float k00,k11; + + float *ee0 = e +i_off; + float *ee2 = ee0+k_off; + + for (i=n; i > 0; --i) { + k00 = ee0[ 0] - ee2[ 0]; + k11 = ee0[-1] - ee2[-1]; + ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = (k00) * A0 - (k11) * A1; + ee2[-1] = (k11) * A0 + (k00) * A1; + + k00 = ee0[-2] - ee2[-2]; + k11 = ee0[-3] - ee2[-3]; + ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = (k00) * A2 - (k11) * A3; + ee2[-3] = (k11) * A2 + (k00) * A3; + + k00 = ee0[-4] - ee2[-4]; + k11 = ee0[-5] - ee2[-5]; + ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = (k00) * A4 - (k11) * A5; + ee2[-5] = (k11) * A4 + (k00) * A5; + + k00 = ee0[-6] - ee2[-6]; + k11 = ee0[-7] - ee2[-7]; + ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = (k00) * A6 - (k11) * A7; + ee2[-7] = (k11) * A6 + (k00) * A7; + + ee0 -= k0; + ee2 -= k0; + } +} + +static __forceinline void iter_54(float *z) +{ + float k00,k11,k22,k33; + float y0,y1,y2,y3; + + k00 = z[ 0] - z[-4]; + y0 = z[ 0] + z[-4]; + y2 = z[-2] + z[-6]; + k22 = z[-2] - z[-6]; + + z[-0] = y0 + y2; // z0 + z4 + z2 + z6 + z[-2] = y0 - y2; // z0 + z4 - z2 - z6 + + // done with y0,y2 + + k33 = z[-3] - z[-7]; + + z[-4] = k00 + k33; // z0 - z4 + z3 - z7 + z[-6] = k00 - k33; // z0 - z4 - z3 + z7 + + // done with k33 + + k11 = z[-1] - z[-5]; + y1 = z[-1] + z[-5]; + y3 = z[-3] + z[-7]; + + z[-1] = y1 + y3; // z1 + z5 + z3 + z7 + z[-3] = y1 - y3; // z1 + z5 - z3 - z7 + z[-5] = k11 - k22; // z1 - z5 + z2 - z6 + z[-7] = k11 + k22; // z1 - z5 - z2 + z6 +} + +static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) +{ + int a_off = base_n >> 3; + float A2 = A[0+a_off]; + float *z = e + i_off; + float *base = z - 16 * n; + + while (z > base) { + float k00,k11; + + k00 = z[-0] - z[-8]; + k11 = z[-1] - z[-9]; + z[-0] = z[-0] + z[-8]; + z[-1] = z[-1] + z[-9]; + z[-8] = k00; + z[-9] = k11 ; + + k00 = z[ -2] - z[-10]; + k11 = z[ -3] - z[-11]; + z[ -2] = z[ -2] + z[-10]; + z[ -3] = z[ -3] + z[-11]; + z[-10] = (k00+k11) * A2; + z[-11] = (k11-k00) * A2; + + k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation + k11 = z[ -5] - z[-13]; + z[ -4] = z[ -4] + z[-12]; + z[ -5] = z[ -5] + z[-13]; + z[-12] = k11; + z[-13] = k00; + + k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation + k11 = z[ -7] - z[-15]; + z[ -6] = z[ -6] + z[-14]; + z[ -7] = z[ -7] + z[-15]; + z[-14] = (k00+k11) * A2; + z[-15] = (k00-k11) * A2; + + iter_54(z); + iter_54(z-8); + z -= 16; + } +} + +static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int ld; + // @OPTIMIZE: reduce register pressure by using fewer variables? + int save_point = temp_alloc_save(f); + float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2)); + float *u=NULL,*v=NULL; + // twiddle factors + float *A = f->A[blocktype]; + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. + + // kernel from paper + + + // merged: + // copy and reflect spectral data + // step 0 + + // note that it turns out that the items added together during + // this step are, in fact, being added to themselves (as reflected + // by step 0). inexplicable inefficiency! this became obvious + // once I combined the passes. + + // so there's a missing 'times 2' here (for adding X to itself). + // this propogates through linearly to the end, where the numbers + // are 1/2 too small, and need to be compensated for. + + { + float *d,*e, *AA, *e_stop; + d = &buf2[n2-2]; + AA = A; + e = &buffer[0]; + e_stop = &buffer[n2]; + while (e != e_stop) { + d[1] = (e[0] * AA[0] - e[2]*AA[1]); + d[0] = (e[0] * AA[1] + e[2]*AA[0]); + d -= 2; + AA += 2; + e += 4; + } + + e = &buffer[n2-3]; + while (d >= buf2) { + d[1] = (-e[2] * AA[0] - -e[0]*AA[1]); + d[0] = (-e[2] * AA[1] + -e[0]*AA[0]); + d -= 2; + AA += 2; + e -= 4; + } + } + + // now we use symbolic names for these, so that we can + // possibly swap their meaning as we change which operations + // are in place + + u = buffer; + v = buf2; + + // step 2 (paper output is w, now u) + // this could be in place, but the data ends up in the wrong + // place... _somebody_'s got to swap it, so this is nominated + { + float *AA = &A[n2-8]; + float *d0,*d1, *e0, *e1; + + e0 = &v[n4]; + e1 = &v[0]; + + d0 = &u[n4]; + d1 = &u[0]; + + while (AA >= A) { + float v40_20, v41_21; + + v41_21 = e0[1] - e1[1]; + v40_20 = e0[0] - e1[0]; + d0[1] = e0[1] + e1[1]; + d0[0] = e0[0] + e1[0]; + d1[1] = v41_21*AA[4] - v40_20*AA[5]; + d1[0] = v40_20*AA[4] + v41_21*AA[5]; + + v41_21 = e0[3] - e1[3]; + v40_20 = e0[2] - e1[2]; + d0[3] = e0[3] + e1[3]; + d0[2] = e0[2] + e1[2]; + d1[3] = v41_21*AA[0] - v40_20*AA[1]; + d1[2] = v40_20*AA[0] + v41_21*AA[1]; + + AA -= 8; + + d0 += 4; + d1 += 4; + e0 += 4; + e1 += 4; + } + } + + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + + // optimized step 3: + + // the original step3 loop can be nested r inside s or s inside r; + // it's written originally as s inside r, but this is dumb when r + // iterates many times, and s few. So I have two copies of it and + // switch between them halfway. + + // this is iteration 0 of step 3 + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A); + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A); + + // this is iteration 1 of step 3 + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16); + + l=2; + for (; l < (ld-3)>>1; ++l) { + int k0 = n >> (l+2), k0_2 = k0>>1; + int lim = 1 << (l+1); + int i; + for (i=0; i < lim; ++i) + imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3)); + } + + for (; l < ld-6; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1; + int rlim = n >> (l+6), r; + int lim = 1 << (l+1); + int i_off; + float *A0 = A; + i_off = n2-1; + for (r=rlim; r > 0; --r) { + imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); + A0 += k1*4; + i_off -= 8; + } + } + + // iterations with count: + // ld-6,-5,-4 all interleaved together + // the big win comes from getting rid of needless flops + // due to the constants on pass 5 & 4 being all 1 and 0; + // combining them to be simultaneous to improve cache made little difference + imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n); + + // output is u + + // step 4, 5, and 6 + // cannot be in-place because of step 5 + { + uint16 *bitrev = f->bit_reverse[blocktype]; + // weirdly, I'd have thought reading sequentially and writing + // erratically would have been better than vice-versa, but in + // fact that's not what my testing showed. (That is, with + // j = bitreverse(i), do you read i and write j, or read j and write i.) + + float *d0 = &v[n4-4]; + float *d1 = &v[n2-4]; + while (d0 >= v) { + int k4; + + k4 = bitrev[0]; + d1[3] = u[k4+0]; + d1[2] = u[k4+1]; + d0[3] = u[k4+2]; + d0[2] = u[k4+3]; + + k4 = bitrev[1]; + d1[1] = u[k4+0]; + d1[0] = u[k4+1]; + d0[1] = u[k4+2]; + d0[0] = u[k4+3]; + + d0 -= 4; + d1 -= 4; + bitrev += 2; + } + } + // (paper output is u, now v) + + + // data must be in buf2 + assert(v == buf2); + + // step 7 (paper output is v, now v) + // this is now in place + { + float *C = f->C[blocktype]; + float *d, *e; + + d = v; + e = v + n2 - 4; + + while (d < e) { + float a02,a11,b0,b1,b2,b3; + + a02 = d[0] - e[2]; + a11 = d[1] + e[3]; + + b0 = C[1]*a02 + C[0]*a11; + b1 = C[1]*a11 - C[0]*a02; + + b2 = d[0] + e[ 2]; + b3 = d[1] - e[ 3]; + + d[0] = b2 + b0; + d[1] = b3 + b1; + e[2] = b2 - b0; + e[3] = b1 - b3; + + a02 = d[2] - e[0]; + a11 = d[3] + e[1]; + + b0 = C[3]*a02 + C[2]*a11; + b1 = C[3]*a11 - C[2]*a02; + + b2 = d[2] + e[ 0]; + b3 = d[3] - e[ 1]; + + d[2] = b2 + b0; + d[3] = b3 + b1; + e[0] = b2 - b0; + e[1] = b1 - b3; + + C += 4; + d += 4; + e -= 4; + } + } + + // data must be in buf2 + + + // step 8+decode (paper output is X, now buffer) + // this generates pairs of data a la 8 and pushes them directly through + // the decode kernel (pushing rather than pulling) to avoid having + // to make another pass later + + // this cannot POSSIBLY be in place, so we refer to the buffers directly + + { + float *d0,*d1,*d2,*d3; + + float *B = f->B[blocktype] + n2 - 8; + float *e = buf2 + n2 - 8; + d0 = &buffer[0]; + d1 = &buffer[n2-4]; + d2 = &buffer[n2]; + d3 = &buffer[n-4]; + while (e >= v) { + float p0,p1,p2,p3; + + p3 = e[6]*B[7] - e[7]*B[6]; + p2 = -e[6]*B[6] - e[7]*B[7]; + + d0[0] = p3; + d1[3] = - p3; + d2[0] = p2; + d3[3] = p2; + + p1 = e[4]*B[5] - e[5]*B[4]; + p0 = -e[4]*B[4] - e[5]*B[5]; + + d0[1] = p1; + d1[2] = - p1; + d2[1] = p0; + d3[2] = p0; + + p3 = e[2]*B[3] - e[3]*B[2]; + p2 = -e[2]*B[2] - e[3]*B[3]; + + d0[2] = p3; + d1[1] = - p3; + d2[2] = p2; + d3[1] = p2; + + p1 = e[0]*B[1] - e[1]*B[0]; + p0 = -e[0]*B[0] - e[1]*B[1]; + + d0[3] = p1; + d1[0] = - p1; + d2[3] = p0; + d3[0] = p0; + + B -= 8; + e -= 8; + d0 += 4; + d2 += 4; + d1 -= 4; + d3 -= 4; + } + } + + temp_alloc_restore(f,save_point); +} + +#if 0 +// this is the original version of the above code, if you want to optimize it from scratch +void inverse_mdct_naive(float *buffer, int n) +{ + float s; + float A[1 << 12], B[1 << 12], C[1 << 11]; + int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int n3_4 = n - n4, ld; + // how can they claim this only uses N words?! + // oh, because they're only used sparsely, whoops + float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13]; + // set up twiddle factors + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2); + B[k2+1] = (float) sin((k2+1)*M_PI/n/2); + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // Note there are bugs in that pseudocode, presumably due to them attempting + // to rename the arrays nicely rather than representing the way their actual + // implementation bounces buffers back and forth. As a result, even in the + // "some formulars corrected" version, a direct implementation fails. These + // are noted below as "paper bug". + + // copy and reflect spectral data + for (k=0; k < n2; ++k) u[k] = buffer[k]; + for ( ; k < n ; ++k) u[k] = -buffer[n - k - 1]; + // kernel from paper + // step 1 + for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) { + v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2] - (u[k4+2] - u[n-k4-3])*A[k2+1]; + v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2]; + } + // step 2 + for (k=k4=0; k < n8; k+=1, k4+=4) { + w[n2+3+k4] = v[n2+3+k4] + v[k4+3]; + w[n2+1+k4] = v[n2+1+k4] + v[k4+1]; + w[k4+3] = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4]; + w[k4+1] = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4]; + } + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + for (l=0; l < ld-3; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3); + int rlim = n >> (l+4), r4, r; + int s2lim = 1 << (l+2), s2; + for (r=r4=0; r < rlim; r4+=4,++r) { + for (s2=0; s2 < s2lim; s2+=2) { + u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4]; + u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4]; + u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1] + - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1]; + u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1] + + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1]; + } + } + if (l+1 < ld-3) { + // paper bug: ping-ponging of u&w here is omitted + memcpy(w, u, sizeof(u)); + } + } + + // step 4 + for (i=0; i < n8; ++i) { + int j = bit_reverse(i) >> (32-ld+3); + assert(j < n8); + if (i == j) { + // paper bug: original code probably swapped in place; if copying, + // need to directly copy in this case + int i8 = i << 3; + v[i8+1] = u[i8+1]; + v[i8+3] = u[i8+3]; + v[i8+5] = u[i8+5]; + v[i8+7] = u[i8+7]; + } else if (i < j) { + int i8 = i << 3, j8 = j << 3; + v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1]; + v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3]; + v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5]; + v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7]; + } + } + // step 5 + for (k=0; k < n2; ++k) { + w[k] = v[k*2+1]; + } + // step 6 + for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) { + u[n-1-k2] = w[k4]; + u[n-2-k2] = w[k4+1]; + u[n3_4 - 1 - k2] = w[k4+2]; + u[n3_4 - 2 - k2] = w[k4+3]; + } + // step 7 + for (k=k2=0; k < n8; ++k, k2 += 2) { + v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + } + // step 8 + for (k=k2=0; k < n4; ++k,k2 += 2) { + X[k] = v[k2+n2]*B[k2 ] + v[k2+1+n2]*B[k2+1]; + X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2 ]; + } + + // decode kernel to output + // determined the following value experimentally + // (by first figuring out what made inverse_mdct_slow work); then matching that here + // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?) + s = 0.5; // theoretically would be n4 + + // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code, + // so it needs to use the "old" B values to behave correctly, or else + // set s to 1.0 ]]] + for (i=0; i < n4 ; ++i) buffer[i] = s * X[i+n4]; + for ( ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1]; + for ( ; i < n ; ++i) buffer[i] = -s * X[i - n3_4]; +} +#endif + +static float *get_window(vorb *f, int len) +{ + len <<= 1; + if (len == f->blocksize_0) return f->window[0]; + if (len == f->blocksize_1) return f->window[1]; + assert(0); + return NULL; +} + +#ifndef STB_VORBIS_NO_DEFER_FLOOR +typedef int16 YTYPE; +#else +typedef int YTYPE; +#endif +static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag) +{ + int n2 = n >> 1; + int s = map->chan[i].mux, floor; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + int j,q; + int lx = 0, ly = finalY[0] * g->floor1_multiplier; + for (q=1; q < g->values; ++q) { + j = g->sorted_order[q]; + #ifndef STB_VORBIS_NO_DEFER_FLOOR + if (finalY[j] >= 0) + #else + if (step2_flag[j]) + #endif + { + int hy = finalY[j] * g->floor1_multiplier; + int hx = g->Xlist[j]; + draw_line(target, lx,ly, hx,hy, n2); + lx = hx, ly = hy; + } + } + if (lx < n2) + // optimization of: draw_line(target, lx,ly, n,ly, n2); + for (j=lx; j < n2; ++j) + LINE_OP(target[j], inverse_db_table[ly]); + } + return TRUE; +} + +// The meaning of "left" and "right" +// +// For a given frame: +// we compute samples from 0..n +// window_center is n/2 +// we'll window and mix the samples from left_start to left_end with data from the previous frame +// all of the samples from left_end to right_start can be output without mixing; however, +// this interval is 0-length except when transitioning between short and long frames +// all of the samples from right_start to right_end need to be mixed with the next frame, +// which we don't have, so those get saved in a buffer +// frame N's right_end-right_start, the number of samples to mix with the next frame, +// has to be the same as frame N+1's left_end-left_start (which they are by +// construction) + +static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +{ + Mode *m; + int i, n, prev, next, window_center; + f->channel_buffer_start = f->channel_buffer_end = 0; + + retry: + if (f->eof) return FALSE; + if (!maybe_start_packet(f)) + return FALSE; + // check packet type + if (get_bits(f,1) != 0) { + if (IS_PUSH_MODE(f)) + return error(f,VORBIS_bad_packet_type); + while (EOP != get8_packet(f)); + goto retry; + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + i = get_bits(f, ilog(f->mode_count-1)); + if (i == EOP) return FALSE; + if (i >= f->mode_count) return FALSE; + *mode = i; + m = f->mode_config + i; + if (m->blockflag) { + n = f->blocksize_1; + prev = get_bits(f,1); + next = get_bits(f,1); + } else { + prev = next = 0; + n = f->blocksize_0; + } + +// WINDOWING + + window_center = n >> 1; + if (m->blockflag && !prev) { + *p_left_start = (n - f->blocksize_0) >> 2; + *p_left_end = (n + f->blocksize_0) >> 2; + } else { + *p_left_start = 0; + *p_left_end = window_center; + } + if (m->blockflag && !next) { + *p_right_start = (n*3 - f->blocksize_0) >> 2; + *p_right_end = (n*3 + f->blocksize_0) >> 2; + } else { + *p_right_start = window_center; + *p_right_end = n; + } + return TRUE; +} + +static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left) +{ + Mapping *map; + int i,j,k,n,n2; + int zero_channel[256]; + int really_zero_channel[256]; + +// WINDOWING + + n = f->blocksize[m->blockflag]; + map = &f->mapping[m->mapping]; + +// FLOORS + n2 = n >> 1; + + stb_prof(1); + for (i=0; i < f->channels; ++i) { + int s = map->chan[i].mux, floor; + zero_channel[i] = FALSE; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + if (get_bits(f, 1)) { + short *finalY; + uint8 step2_flag[256]; + static int range_list[4] = { 256, 128, 86, 64 }; + int range = range_list[g->floor1_multiplier-1]; + int offset = 2; + finalY = f->finalY[i]; + finalY[0] = get_bits(f, ilog(range)-1); + finalY[1] = get_bits(f, ilog(range)-1); + for (j=0; j < g->partitions; ++j) { + int pclass = g->partition_class_list[j]; + int cdim = g->class_dimensions[pclass]; + int cbits = g->class_subclasses[pclass]; + int csub = (1 << cbits)-1; + int cval = 0; + if (cbits) { + Codebook *c = f->codebooks + g->class_masterbooks[pclass]; + DECODE(cval,f,c); + } + for (k=0; k < cdim; ++k) { + int book = g->subclass_books[pclass][cval & csub]; + cval = cval >> cbits; + if (book >= 0) { + int temp; + Codebook *c = f->codebooks + book; + DECODE(temp,f,c); + finalY[offset++] = temp; + } else + finalY[offset++] = 0; + } + } + if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec + step2_flag[0] = step2_flag[1] = 1; + for (j=2; j < g->values; ++j) { + int low, high, pred, highroom, lowroom, room, val; + low = g->neighbors[j][0]; + high = g->neighbors[j][1]; + //neighbors(g->Xlist, j, &low, &high); + pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); + val = finalY[j]; + highroom = range - pred; + lowroom = pred; + if (highroom < lowroom) + room = highroom * 2; + else + room = lowroom * 2; + if (val) { + step2_flag[low] = step2_flag[high] = 1; + step2_flag[j] = 1; + if (val >= room) + if (highroom > lowroom) + finalY[j] = val - lowroom + pred; + else + finalY[j] = pred - val + highroom - 1; + else + if (val & 1) + finalY[j] = pred - ((val+1)>>1); + else + finalY[j] = pred + (val>>1); + } else { + step2_flag[j] = 0; + finalY[j] = pred; + } + } + +#ifdef STB_VORBIS_NO_DEFER_FLOOR + do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag); +#else + // defer final floor computation until _after_ residue + for (j=0; j < g->values; ++j) { + if (!step2_flag[j]) + finalY[j] = -1; + } +#endif + } else { + error: + zero_channel[i] = TRUE; + } + // So we just defer everything else to later + + // at this point we've decoded the floor into buffer + } + } + stb_prof(0); + // at this point we've decoded all floors + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + // re-enable coupled channels if necessary + memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); + for (i=0; i < map->coupling_steps; ++i) + if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) { + zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; + } + +// RESIDUE DECODE + for (i=0; i < map->submaps; ++i) { + float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; + int r; + uint8 do_not_decode[256]; + int ch = 0; + for (j=0; j < f->channels; ++j) { + if (map->chan[j].mux == i) { + if (zero_channel[j]) { + do_not_decode[ch] = TRUE; + residue_buffers[ch] = NULL; + } else { + do_not_decode[ch] = FALSE; + residue_buffers[ch] = f->channel_buffers[j]; + } + ++ch; + } + } + r = map->submap_residue[i]; + decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + +// INVERSE COUPLING + stb_prof(14); + for (i = map->coupling_steps-1; i >= 0; --i) { + int n2 = n >> 1; + float *m = f->channel_buffers[map->chan[i].magnitude]; + float *a = f->channel_buffers[map->chan[i].angle ]; + for (j=0; j < n2; ++j) { + float a2,m2; + if (m[j] > 0) + if (a[j] > 0) + m2 = m[j], a2 = m[j] - a[j]; + else + a2 = m[j], m2 = m[j] + a[j]; + else + if (a[j] > 0) + m2 = m[j], a2 = m[j] + a[j]; + else + a2 = m[j], m2 = m[j] - a[j]; + m[j] = m2; + a[j] = a2; + } + } + + // finish decoding the floors +#ifndef STB_VORBIS_NO_DEFER_FLOOR + stb_prof(15); + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); + } + } +#else + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + for (j=0; j < n2; ++j) + f->channel_buffers[i][j] *= f->floor_buffers[i][j]; + } + } +#endif + +// INVERSE MDCT + stb_prof(16); + for (i=0; i < f->channels; ++i) + inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); + stb_prof(0); + + // this shouldn't be necessary, unless we exited on an error + // and want to flush to get to the next packet + flush_packet(f); + + if (f->first_decode) { + // assume we start so first non-discarded sample is sample 0 + // this isn't to spec, but spec would require us to read ahead + // and decode the size of all current frames--could be done, + // but presumably it's not a commonly used feature + f->current_loc = -n2; // start of first frame is positioned for discard + // we might have to discard samples "from" the next frame too, + // if we're lapping a large block then a small at the start? + f->discard_samples_deferred = n - right_end; + f->current_loc_valid = TRUE; + f->first_decode = FALSE; + } else if (f->discard_samples_deferred) { + left_start += f->discard_samples_deferred; + *p_left = left_start; + f->discard_samples_deferred = 0; + } else if (f->previous_length == 0 && f->current_loc_valid) { + // we're recovering from a seek... that means we're going to discard + // the samples from this packet even though we know our position from + // the last page header, so we need to update the position based on + // the discarded samples here + // but wait, the code below is going to add this in itself even + // on a discard, so we don't need to do it here... + } + + // check if we have ogg information about the sample # for this packet + if (f->last_seg_which == f->end_seg_with_known_loc) { + // if we have a valid current loc, and this is final: + if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { + uint32 current_end = f->known_loc_for_packet - (n-right_end); + // then let's infer the size of the (probably) short final frame + if (current_end < f->current_loc + right_end) { + if (current_end < f->current_loc) { + // negative truncation, that's impossible! + *len = 0; + } else { + *len = current_end - f->current_loc; + } + *len += left_start; + f->current_loc += *len; + return TRUE; + } + } + // otherwise, just set our sample loc + // guess that the ogg granule pos refers to the _middle_ of the + // last frame? + // set f->current_loc to the position of left_start + f->current_loc = f->known_loc_for_packet - (n2-left_start); + f->current_loc_valid = TRUE; + } + if (f->current_loc_valid) + f->current_loc += (right_start - left_start); + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + *len = right_end; // ignore samples after the window goes to 0 + return TRUE; +} + +static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right) +{ + int mode, left_end, right_end; + if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; + return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); +} + +static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) +{ + int prev,i,j; + // we use right&left (the start of the right- and left-window sin()-regions) + // to determine how much to return, rather than inferring from the rules + // (same result, clearer code); 'left' indicates where our sin() window + // starts, therefore where the previous window's right edge starts, and + // therefore where to start mixing from the previous buffer. 'right' + // indicates where our sin() ending-window starts, therefore that's where + // we start saving, and where our returned-data ends. + + // mixin from previous window + if (f->previous_length) { + int i,j, n = f->previous_length; + float *w = get_window(f, n); + for (i=0; i < f->channels; ++i) { + for (j=0; j < n; ++j) + f->channel_buffers[i][left+j] = + f->channel_buffers[i][left+j]*w[ j] + + f->previous_window[i][ j]*w[n-1-j]; + } + } + + prev = f->previous_length; + + // last half of this data becomes previous window + f->previous_length = len - right; + + // @OPTIMIZE: could avoid this copy by double-buffering the + // output (flipping previous_window with channel_buffers), but + // then previous_window would have to be 2x as large, and + // channel_buffers couldn't be temp mem (although they're NOT + // currently temp mem, they could be (unless we want to level + // performance by spreading out the computation)) + for (i=0; i < f->channels; ++i) + for (j=0; right+j < len; ++j) + f->previous_window[i][j] = f->channel_buffers[i][right+j]; + + if (!prev) + // there was no previous packet, so this data isn't valid... + // this isn't entirely true, only the would-have-overlapped data + // isn't valid, but this seems to be what the spec requires + return 0; + + // truncate a short frame + if (len < right) right = len; + + f->samples_output += right-left; + + return right - left; +} + +static void vorbis_pump_first_frame(stb_vorbis *f) +{ + int len, right, left; + if (vorbis_decode_packet(f, &len, &left, &right)) + vorbis_finish_frame(f, len, left, right); +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API +static int is_whole_packet_present(stb_vorbis *f, int end_page) +{ + // make sure that we have the packet available before continuing... + // this requires a full ogg parse, but we know we can fetch from f->stream + + // instead of coding this out explicitly, we could save the current read state, + // read the next packet with get8() until end-of-packet, check f->eof, then + // reset the state? but that would be slower, esp. since we'd have over 256 bytes + // of state to restore (primarily the page segment table) + + int s = f->next_seg, first = TRUE; + uint8 *p = f->stream; + + if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag + for (; s < f->segment_count; ++s) { + p += f->segments[s]; + if (f->segments[s] < 255) // stop at first short segment + break; + } + // either this continues, or it ends it... + if (end_page) + if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream); + if (s == f->segment_count) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + for (; s == -1;) { + uint8 *q; + int n; + + // check that we have the page header ready + if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); + // validate the page + if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); + if (p[4] != 0) return error(f, VORBIS_invalid_stream); + if (first) { // the first segment must NOT have 'continued_packet', later ones MUST + if (f->previous_length) + if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + // if no previous length, we're resynching, so we can come in on a continued-packet, + // which we'll just drop + } else { + if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + } + n = p[26]; // segment counts + q = p+27; // q points to segment table + p = q + n; // advance past header + // make sure we've read the segment table + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + for (s=0; s < n; ++s) { + p += q[s]; + if (q[s] < 255) + break; + } + if (end_page) + if (s < n-1) return error(f, VORBIS_invalid_stream); + if (s == n) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + return TRUE; +} +#endif // !STB_VORBIS_NO_PUSHDATA_API + +static int start_decoder(vorb *f) +{ + uint8 header[6], x,y; + int len,i,j,k, max_submaps = 0; + int longest_floorlist=0; + + // first page, first packet + + if (!start_page(f)) return FALSE; + // validate page flag + if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); + // check for expected packet length + if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); + if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page); + // read packet + // check packet header + if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); + if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); + // vorbis_version + if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); + f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page); + if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); + f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); + get32(f); // bitrate_maximum + get32(f); // bitrate_nominal + get32(f); // bitrate_minimum + x = get8(f); + { int log0,log1; + log0 = x & 15; + log1 = x >> 4; + f->blocksize_0 = 1 << log0; + f->blocksize_1 = 1 << log1; + if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); + if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); + if (log0 > log1) return error(f, VORBIS_invalid_setup); + } + + // framing_flag + x = get8(f); + if (!(x & 1)) return error(f, VORBIS_invalid_first_page); + + // second packet! + if (!start_page(f)) return FALSE; + + if (!start_packet(f)) return FALSE; + do { + len = next_segment(f); + skip(f, len); + f->bytes_in_seg = 0; + } while (len); + + // third packet! + if (!start_packet(f)) return FALSE; + + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (IS_PUSH_MODE(f)) { + if (!is_whole_packet_present(f, TRUE)) { + // convert error in ogg header to write type + if (f->error == VORBIS_invalid_stream) + f->error = VORBIS_invalid_setup; + return FALSE; + } + } + #endif + + crc32_init(); // always init it, to avoid multithread race conditions + + if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); + for (i=0; i < 6; ++i) header[i] = get8_packet(f); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); + + // codebooks + + f->codebook_count = get_bits(f,8) + 1; + f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); + if (f->codebooks == NULL) return error(f, VORBIS_outofmem); + memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); + for (i=0; i < f->codebook_count; ++i) { + uint32 *values; + int ordered, sorted_count; + int total=0; + uint8 *lengths; + Codebook *c = f->codebooks+i; + x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); + c->dimensions = (get_bits(f, 8)<<8) + x; + x = get_bits(f, 8); + y = get_bits(f, 8); + c->entries = (get_bits(f, 8)<<16) + (y<<8) + x; + ordered = get_bits(f,1); + c->sparse = ordered ? 0 : get_bits(f,1); + + if (c->sparse) + lengths = (uint8 *) setup_temp_malloc(f, c->entries); + else + lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + + if (!lengths) return error(f, VORBIS_outofmem); + + if (ordered) { + int current_entry = 0; + int current_length = get_bits(f,5) + 1; + while (current_entry < c->entries) { + int limit = c->entries - current_entry; + int n = get_bits(f, ilog(limit)); + if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } + memset(lengths + current_entry, current_length, n); + current_entry += n; + ++current_length; + } + } else { + for (j=0; j < c->entries; ++j) { + int present = c->sparse ? get_bits(f,1) : 1; + if (present) { + lengths[j] = get_bits(f, 5) + 1; + ++total; + } else { + lengths[j] = NO_CODE; + } + } + } + + if (c->sparse && total >= c->entries >> 2) { + // convert sparse items to non-sparse! + if (c->entries > (int) f->setup_temp_memory_required) + f->setup_temp_memory_required = c->entries; + + c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + memcpy(c->codeword_lengths, lengths, c->entries); + setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! + lengths = c->codeword_lengths; + c->sparse = 0; + } + + // compute the size of the sorted tables + if (c->sparse) { + sorted_count = total; + } else { + sorted_count = 0; + #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + for (j=0; j < c->entries; ++j) + if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) + ++sorted_count; + #endif + } + + c->sorted_entries = sorted_count; + values = NULL; + + if (!c->sparse) { + c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + } else { + unsigned int size; + if (c->sorted_entries) { + c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries); + if (!c->codeword_lengths) return error(f, VORBIS_outofmem); + c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); + if (!values) return error(f, VORBIS_outofmem); + } + size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; + if (size > f->setup_temp_memory_required) + f->setup_temp_memory_required = size; + } + + if (!compute_codewords(c, lengths, c->entries, values)) { + if (c->sparse) setup_temp_free(f, values, 0); + return error(f, VORBIS_invalid_setup); + } + + if (c->sorted_entries) { + // allocate an extra slot for sentinels + c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); + // allocate an extra slot at the front so that c->sorted_values[-1] is defined + // so that we can catch that case without an extra if + c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); + if (c->sorted_values) { ++c->sorted_values; c->sorted_values[-1] = -1; } + compute_sorted_huffman(c, lengths, values); + } + + if (c->sparse) { + setup_temp_free(f, values, sizeof(*values)*c->sorted_entries); + setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries); + setup_temp_free(f, lengths, c->entries); + c->codewords = NULL; + } + + compute_accelerated_huffman(c); + + c->lookup_type = get_bits(f, 4); + if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); + if (c->lookup_type > 0) { + uint16 *mults; + c->minimum_value = float32_unpack(get_bits(f, 32)); + c->delta_value = float32_unpack(get_bits(f, 32)); + c->value_bits = get_bits(f, 4)+1; + c->sequence_p = get_bits(f,1); + if (c->lookup_type == 1) { + c->lookup_values = lookup1_values(c->entries, c->dimensions); + } else { + c->lookup_values = c->entries * c->dimensions; + } + mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); + if (mults == NULL) return error(f, VORBIS_outofmem); + for (j=0; j < (int) c->lookup_values; ++j) { + int q = get_bits(f, c->value_bits); + if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); } + mults[j] = q; + } + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int len, sparse = c->sparse; + // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop + if (sparse) { + if (c->sorted_entries == 0) goto skip; + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); + } else + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); + if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } + len = sparse ? c->sorted_entries : c->entries; + for (j=0; j < len; ++j) { + int z = sparse ? c->sorted_values[j] : j, div=1; + for (k=0; k < c->dimensions; ++k) { + int off = (z / div) % c->lookup_values; + c->multiplicands[j*c->dimensions + k] = + #ifndef STB_VORBIS_CODEBOOK_FLOATS + mults[off]; + #else + mults[off]*c->delta_value + c->minimum_value; + // in this case (and this case only) we could pre-expand c->sequence_p, + // and throw away the decode logic for it; have to ALSO do + // it in the case below, but it can only be done if + // STB_VORBIS_CODEBOOK_FLOATS + // !STB_VORBIS_DIVIDES_IN_CODEBOOK + #endif + div *= c->lookup_values; + } + } + setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); + c->lookup_type = 2; + } + else +#endif + { + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); + #ifndef STB_VORBIS_CODEBOOK_FLOATS + memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values); + #else + for (j=0; j < (int) c->lookup_values; ++j) + c->multiplicands[j] = mults[j] * c->delta_value + c->minimum_value; + #endif + setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); + } +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + skip:; +#endif + + #ifdef STB_VORBIS_CODEBOOK_FLOATS + if (c->lookup_type == 2 && c->sequence_p) { + for (j=1; j < (int) c->lookup_values; ++j) + c->multiplicands[j] = c->multiplicands[j-1]; + c->sequence_p = 0; + } + #endif + } + } + + // time domain transfers (notused) + + x = get_bits(f, 6) + 1; + for (i=0; i < x; ++i) { + uint32 z = get_bits(f, 16); + if (z != 0) return error(f, VORBIS_invalid_setup); + } + + // Floors + f->floor_count = get_bits(f, 6)+1; + f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); + for (i=0; i < f->floor_count; ++i) { + f->floor_types[i] = get_bits(f, 16); + if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); + if (f->floor_types[i] == 0) { + Floor0 *g = &f->floor_config[i].floor0; + g->order = get_bits(f,8); + g->rate = get_bits(f,16); + g->bark_map_size = get_bits(f,16); + g->amplitude_bits = get_bits(f,6); + g->amplitude_offset = get_bits(f,8); + g->number_of_books = get_bits(f,4) + 1; + for (j=0; j < g->number_of_books; ++j) + g->book_list[j] = get_bits(f,8); + return error(f, VORBIS_feature_not_supported); + } else { + Point p[31*8+2]; + Floor1 *g = &f->floor_config[i].floor1; + int max_class = -1; + g->partitions = get_bits(f, 5); + for (j=0; j < g->partitions; ++j) { + g->partition_class_list[j] = get_bits(f, 4); + if (g->partition_class_list[j] > max_class) + max_class = g->partition_class_list[j]; + } + for (j=0; j <= max_class; ++j) { + g->class_dimensions[j] = get_bits(f, 3)+1; + g->class_subclasses[j] = get_bits(f, 2); + if (g->class_subclasses[j]) { + g->class_masterbooks[j] = get_bits(f, 8); + if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + for (k=0; k < 1 << g->class_subclasses[j]; ++k) { + g->subclass_books[j][k] = get_bits(f,8)-1; + if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + } + g->floor1_multiplier = get_bits(f,2)+1; + g->rangebits = get_bits(f,4); + g->Xlist[0] = 0; + g->Xlist[1] = 1 << g->rangebits; + g->values = 2; + for (j=0; j < g->partitions; ++j) { + int c = g->partition_class_list[j]; + for (k=0; k < g->class_dimensions[c]; ++k) { + g->Xlist[g->values] = get_bits(f, g->rangebits); + ++g->values; + } + } + // precompute the sorting + for (j=0; j < g->values; ++j) { + p[j].x = g->Xlist[j]; + p[j].y = j; + } + qsort(p, g->values, sizeof(p[0]), point_compare); + for (j=0; j < g->values; ++j) + g->sorted_order[j] = (uint8) p[j].y; + // precompute the neighbors + for (j=2; j < g->values; ++j) { + int low,hi; + neighbors(g->Xlist, j, &low,&hi); + g->neighbors[j][0] = low; + g->neighbors[j][1] = hi; + } + + if (g->values > longest_floorlist) + longest_floorlist = g->values; + } + } + + // Residue + f->residue_count = get_bits(f, 6)+1; + f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(*f->residue_config)); + for (i=0; i < f->residue_count; ++i) { + uint8 residue_cascade[64]; + Residue *r = f->residue_config+i; + f->residue_types[i] = get_bits(f, 16); + if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); + r->begin = get_bits(f, 24); + r->end = get_bits(f, 24); + r->part_size = get_bits(f,24)+1; + r->classifications = get_bits(f,6)+1; + r->classbook = get_bits(f,8); + for (j=0; j < r->classifications; ++j) { + uint8 high_bits=0; + uint8 low_bits=get_bits(f,3); + if (get_bits(f,1)) + high_bits = get_bits(f,5); + residue_cascade[j] = high_bits*8 + low_bits; + } + r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); + for (j=0; j < r->classifications; ++j) { + for (k=0; k < 8; ++k) { + if (residue_cascade[j] & (1 << k)) { + r->residue_books[j][k] = get_bits(f, 8); + if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } else { + r->residue_books[j][k] = -1; + } + } + } + // precompute the classifications[] array to avoid inner-loop mod/divide + // call it 'classdata' since we already have r->classifications + r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + if (!r->classdata) return error(f, VORBIS_outofmem); + memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + for (j=0; j < f->codebooks[r->classbook].entries; ++j) { + int classwords = f->codebooks[r->classbook].dimensions; + int temp = j; + r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); + for (k=classwords-1; k >= 0; --k) { + r->classdata[j][k] = temp % r->classifications; + temp /= r->classifications; + } + } + } + + f->mapping_count = get_bits(f,6)+1; + f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); + for (i=0; i < f->mapping_count; ++i) { + Mapping *m = f->mapping + i; + int mapping_type = get_bits(f,16); + if (mapping_type != 0) return error(f, VORBIS_invalid_setup); + m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); + if (get_bits(f,1)) + m->submaps = get_bits(f,4)+1; + else + m->submaps = 1; + if (m->submaps > max_submaps) + max_submaps = m->submaps; + if (get_bits(f,1)) { + m->coupling_steps = get_bits(f,8)+1; + for (k=0; k < m->coupling_steps; ++k) { + m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); + m->chan[k].angle = get_bits(f, ilog(f->channels-1)); + if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); + } + } else + m->coupling_steps = 0; + + // reserved field + if (get_bits(f,2)) return error(f, VORBIS_invalid_setup); + if (m->submaps > 1) { + for (j=0; j < f->channels; ++j) { + m->chan[j].mux = get_bits(f, 4); + if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); + } + } else + // @SPECIFICATION: this case is missing from the spec + for (j=0; j < f->channels; ++j) + m->chan[j].mux = 0; + + for (j=0; j < m->submaps; ++j) { + get_bits(f,8); // discard + m->submap_floor[j] = get_bits(f,8); + m->submap_residue[j] = get_bits(f,8); + if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); + if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); + } + } + + // Modes + f->mode_count = get_bits(f, 6)+1; + for (i=0; i < f->mode_count; ++i) { + Mode *m = f->mode_config+i; + m->blockflag = get_bits(f,1); + m->windowtype = get_bits(f,16); + m->transformtype = get_bits(f,16); + m->mapping = get_bits(f,8); + if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); + if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); + if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); + } + + flush_packet(f); + + f->previous_length = 0; + + for (i=0; i < f->channels; ++i) { + f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); + f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + #endif + } + + if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; + if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; + f->blocksize[0] = f->blocksize_0; + f->blocksize[1] = f->blocksize_1; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (integer_divide_table[1][1]==0) + for (i=0; i < DIVTAB_NUMER; ++i) + for (j=1; j < DIVTAB_DENOM; ++j) + integer_divide_table[i][j] = i / j; +#endif + + // compute how much temporary memory is needed + + // 1. + { + uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); + uint32 classify_mem; + int i,max_part_read=0; + for (i=0; i < f->residue_count; ++i) { + Residue *r = f->residue_config + i; + int n_read = r->end - r->begin; + int part_read = n_read / r->part_size; + if (part_read > max_part_read) + max_part_read = part_read; + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *)); + #else + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); + #endif + + f->temp_memory_required = classify_mem; + if (imdct_mem > f->temp_memory_required) + f->temp_memory_required = imdct_mem; + } + + f->first_decode = TRUE; + + if (f->alloc.alloc_buffer) { + assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); + // check if there's enough temp memory so we don't error later + if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset) + return error(f, VORBIS_outofmem); + } + + f->first_audio_page_offset = stb_vorbis_get_file_offset(f); + + return TRUE; +} + +static void vorbis_deinit(stb_vorbis *p) +{ + int i,j; + for (i=0; i < p->residue_count; ++i) { + Residue *r = p->residue_config+i; + if (r->classdata) { + for (j=0; j < p->codebooks[r->classbook].entries; ++j) + setup_free(p, r->classdata[j]); + setup_free(p, r->classdata); + } + setup_free(p, r->residue_books); + } + + if (p->codebooks) { + for (i=0; i < p->codebook_count; ++i) { + Codebook *c = p->codebooks + i; + setup_free(p, c->codeword_lengths); + setup_free(p, c->multiplicands); + setup_free(p, c->codewords); + setup_free(p, c->sorted_codewords); + // c->sorted_values[-1] is the first entry in the array + setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL); + } + setup_free(p, p->codebooks); + } + setup_free(p, p->floor_config); + setup_free(p, p->residue_config); + for (i=0; i < p->mapping_count; ++i) + setup_free(p, p->mapping[i].chan); + setup_free(p, p->mapping); + for (i=0; i < p->channels; ++i) { + setup_free(p, p->channel_buffers[i]); + setup_free(p, p->previous_window[i]); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + setup_free(p, p->floor_buffers[i]); + #endif + setup_free(p, p->finalY[i]); + } + for (i=0; i < 2; ++i) { + setup_free(p, p->A[i]); + setup_free(p, p->B[i]); + setup_free(p, p->C[i]); + setup_free(p, p->window[i]); + setup_free(p, p->bit_reverse[i]); + } + #ifndef STB_VORBIS_NO_STDIO + if (p->close_on_free) fclose(p->f); + #endif +} + +void stb_vorbis_close(stb_vorbis *p) +{ + if (p == NULL) return; + vorbis_deinit(p); + setup_free(p,p); +} + +static void vorbis_init(stb_vorbis *p, stb_vorbis_alloc *z) +{ + memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start + if (z) { + p->alloc = *z; + p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3; + p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; + } + p->eof = 0; + p->error = VORBIS__no_error; + p->stream = NULL; + p->codebooks = NULL; + p->page_crc_tests = -1; + #ifndef STB_VORBIS_NO_STDIO + p->close_on_free = FALSE; + p->f = NULL; + #endif +} + +int stb_vorbis_get_sample_offset(stb_vorbis *f) +{ + if (f->current_loc_valid) + return f->current_loc; + else + return -1; +} + +stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) +{ + stb_vorbis_info d; + d.channels = f->channels; + d.sample_rate = f->sample_rate; + d.setup_memory_required = f->setup_memory_required; + d.setup_temp_memory_required = f->setup_temp_memory_required; + d.temp_memory_required = f->temp_memory_required; + d.max_frame_size = f->blocksize_1 >> 1; + return d; +} + +int stb_vorbis_get_error(stb_vorbis *f) +{ + int e = f->error; + f->error = VORBIS__no_error; + return e; +} + +static stb_vorbis * vorbis_alloc(stb_vorbis *f) +{ + stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p)); + return p; +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +void stb_vorbis_flush_pushdata(stb_vorbis *f) +{ + f->previous_length = 0; + f->page_crc_tests = 0; + f->discard_samples_deferred = 0; + f->current_loc_valid = FALSE; + f->first_decode = FALSE; + f->samples_output = 0; + f->channel_buffer_start = 0; + f->channel_buffer_end = 0; +} + +static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) +{ + int i,n; + for (i=0; i < f->page_crc_tests; ++i) + f->scan[i].bytes_done = 0; + + // if we have room for more scans, search for them first, because + // they may cause us to stop early if their header is incomplete + if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) { + if (data_len < 4) return 0; + data_len -= 3; // need to look for 4-byte sequence, so don't miss + // one that straddles a boundary + for (i=0; i < data_len; ++i) { + if (data[i] == 0x4f) { + if (0==memcmp(data+i, ogg_page_header, 4)) { + int j,len; + uint32 crc; + // make sure we have the whole page header + if (i+26 >= data_len || i+27+data[i+26] >= data_len) { + // only read up to this page start, so hopefully we'll + // have the whole page header start next time + data_len = i; + break; + } + // ok, we have it all; compute the length of the page + len = 27 + data[i+26]; + for (j=0; j < data[i+26]; ++j) + len += data[i+27+j]; + // scan everything up to the embedded crc (which we must 0) + crc = 0; + for (j=0; j < 22; ++j) + crc = crc32_update(crc, data[i+j]); + // now process 4 0-bytes + for ( ; j < 26; ++j) + crc = crc32_update(crc, 0); + // len is the total number of bytes we need to scan + n = f->page_crc_tests++; + f->scan[n].bytes_left = len-j; + f->scan[n].crc_so_far = crc; + f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24); + // if the last frame on a page is continued to the next, then + // we can't recover the sample_loc immediately + if (data[i+27+data[i+26]-1] == 255) + f->scan[n].sample_loc = ~0; + else + f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24); + f->scan[n].bytes_done = i+j; + if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) + break; + // keep going if we still have room for more + } + } + } + } + + for (i=0; i < f->page_crc_tests;) { + uint32 crc; + int j; + int n = f->scan[i].bytes_done; + int m = f->scan[i].bytes_left; + if (m > data_len - n) m = data_len - n; + // m is the bytes to scan in the current chunk + crc = f->scan[i].crc_so_far; + for (j=0; j < m; ++j) + crc = crc32_update(crc, data[n+j]); + f->scan[i].bytes_left -= m; + f->scan[i].crc_so_far = crc; + if (f->scan[i].bytes_left == 0) { + // does it match? + if (f->scan[i].crc_so_far == f->scan[i].goal_crc) { + // Houston, we have page + data_len = n+m; // consumption amount is wherever that scan ended + f->page_crc_tests = -1; // drop out of page scan mode + f->previous_length = 0; // decode-but-don't-output one frame + f->next_seg = -1; // start a new page + f->current_loc = f->scan[i].sample_loc; // set the current sample location + // to the amount we'd have decoded had we decoded this page + f->current_loc_valid = f->current_loc != ~0U; + return data_len; + } + // delete entry + f->scan[i] = f->scan[--f->page_crc_tests]; + } else { + ++i; + } + } + + return data_len; +} + +// return value: number of bytes we used +int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, // the file we're decoding + uint8 *data, int data_len, // the memory available for decoding + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ) +{ + int i; + int len,right,left; + + if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (f->page_crc_tests >= 0) { + *samples = 0; + return vorbis_search_for_page_pushdata(f, data, data_len); + } + + f->stream = data; + f->stream_end = data + data_len; + f->error = VORBIS__no_error; + + // check that we have the entire packet in memory + if (!is_whole_packet_present(f, FALSE)) { + *samples = 0; + return 0; + } + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + // save the actual error we encountered + enum STBVorbisError error = f->error; + if (error == VORBIS_bad_packet_type) { + // flush and resynch + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return f->stream - data; + } + if (error == VORBIS_continued_packet_flag_invalid) { + if (f->previous_length == 0) { + // we may be resynching, in which case it's ok to hit one + // of these; just discard the packet + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return f->stream - data; + } + } + // if we get an error while parsing, what to do? + // well, it DEFINITELY won't work to continue from where we are! + stb_vorbis_flush_pushdata(f); + // restore the error that actually made us bail + f->error = error; + *samples = 0; + return 1; + } + + // success! + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + if (channels) *channels = f->channels; + *samples = len; + *output = f->outputs; + return f->stream - data; +} + +stb_vorbis *stb_vorbis_open_pushdata( + unsigned char *data, int data_len, // the memory available for decoding + int *data_used, // only defined if result is not NULL + int *error, stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.stream = data; + p.stream_end = data + data_len; + p.push_mode = TRUE; + if (!start_decoder(&p)) { + if (p.eof) + *error = VORBIS_need_more_data; + else + *error = p.error; + return NULL; + } + f = vorbis_alloc(&p); + if (f) { + *f = p; + *data_used = f->stream - data; + *error = 0; + return f; + } else { + vorbis_deinit(&p); + return NULL; + } +} +#endif // STB_VORBIS_NO_PUSHDATA_API + +unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + if (USE_MEMORY(f)) return f->stream - f->stream_start; + #ifndef STB_VORBIS_NO_STDIO + return ftell(f->f) - f->f_start; + #endif +} + +#ifndef STB_VORBIS_NO_PULLDATA_API +// +// DATA-PULLING API +// + +static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) +{ + for(;;) { + int n; + if (f->eof) return 0; + n = get8(f); + if (n == 0x4f) { // page header + unsigned int retry_loc = stb_vorbis_get_file_offset(f); + int i; + // check if we're off the end of a file_section stream + if (retry_loc - 25 > f->stream_len) + return 0; + // check the rest of the header + for (i=1; i < 4; ++i) + if (get8(f) != ogg_page_header[i]) + break; + if (f->eof) return 0; + if (i == 4) { + uint8 header[27]; + uint32 i, crc, goal, len; + for (i=0; i < 4; ++i) + header[i] = ogg_page_header[i]; + for (; i < 27; ++i) + header[i] = get8(f); + if (f->eof) return 0; + if (header[4] != 0) goto invalid; + goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24); + for (i=22; i < 26; ++i) + header[i] = 0; + crc = 0; + for (i=0; i < 27; ++i) + crc = crc32_update(crc, header[i]); + len = 0; + for (i=0; i < header[26]; ++i) { + int s = get8(f); + crc = crc32_update(crc, s); + len += s; + } + if (len && f->eof) return 0; + for (i=0; i < len; ++i) + crc = crc32_update(crc, get8(f)); + // finished parsing probable page + if (crc == goal) { + // we could now check that it's either got the last + // page flag set, OR it's followed by the capture + // pattern, but I guess TECHNICALLY you could have + // a file with garbage between each ogg page and recover + // from it automatically? So even though that paranoia + // might decrease the chance of an invalid decode by + // another 2^32, not worth it since it would hose those + // invalid-but-useful files? + if (end) + *end = stb_vorbis_get_file_offset(f); + if (last) { + if (header[5] & 0x04) + *last = 1; + else + *last = 0; + } + set_file_offset(f, retry_loc-1); + return 1; + } + } + invalid: + // not a valid page, so rewind and look for next one + set_file_offset(f, retry_loc); + } + } +} + +// seek is implemented with 'interpolation search'--this is like +// binary search, but we use the data values to estimate the likely +// location of the data item (plus a bit of a bias so when the +// estimation is wrong we don't waste overly much time) + +#define SAMPLE_unknown 0xffffffff + + +// ogg vorbis, in its insane infinite wisdom, only provides +// information about the sample at the END of the page. +// therefore we COULD have the data we need in the current +// page, and not know it. we could just use the end location +// as our only knowledge for bounds, seek back, and eventually +// the binary search finds it. or we can try to be smart and +// not waste time trying to locate more pages. we try to be +// smart, since this data is already in memory anyway, so +// doing needless I/O would be crazy! +static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z) +{ + uint8 header[27], lacing[255]; + uint8 packet_type[255]; + int num_packet, packet_start; + int i,len; + uint32 samples; + + // record where the page starts + z->page_start = stb_vorbis_get_file_offset(f); + + // parse the header + getn(f, header, 27); + assert(header[0] == 'O' && header[1] == 'g' && header[2] == 'g' && header[3] == 'S'); + getn(f, lacing, header[26]); + + // determine the length of the payload + len = 0; + for (i=0; i < header[26]; ++i) + len += lacing[i]; + + // this implies where the page ends + z->page_end = z->page_start + 27 + header[26] + len; + + // read the last-decoded sample out of the data + z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 16); + + if (header[5] & 4) { + // if this is the last page, it's not possible to work + // backwards to figure out the first sample! whoops! fuck. + z->first_decoded_sample = SAMPLE_unknown; + set_file_offset(f, z->page_start); + return 1; + } + + // scan through the frames to determine the sample-count of each one... + // our goal is the sample # of the first fully-decoded sample on the + // page, which is the first decoded sample of the 2nd packet + + num_packet=0; + + packet_start = ((header[5] & 1) == 0); + + for (i=0; i < header[26]; ++i) { + if (packet_start) { + uint8 n,b; + if (lacing[i] == 0) goto bail; // trying to read from zero-length packet + n = get8(f); + // if bottom bit is non-zero, we've got corruption + if (n & 1) goto bail; + n >>= 1; + b = ilog(f->mode_count-1); + n &= (1 << b)-1; + if (n >= f->mode_count) goto bail; + packet_type[num_packet++] = f->mode_config[n].blockflag; + skip(f, lacing[i]-1); + } else + skip(f, lacing[i]); + packet_start = (lacing[i] < 255); + } + + // now that we know the sizes of all the pages, we can start determining + // how much sample data there is. + + samples = 0; + + // for the last packet, we step by its whole length, because the definition + // is that we encoded the end sample loc of the 'last packet completed', + // where 'completed' refers to packets being split, and we are left to guess + // what 'end sample loc' means. we assume it means ignoring the fact that + // the last half of the data is useless without windowing against the next + // packet... (so it's not REALLY complete in that sense) + if (num_packet > 1) + samples += f->blocksize[packet_type[num_packet-1]]; + + for (i=num_packet-2; i >= 1; --i) { + // now, for this packet, how many samples do we have that + // do not overlap the following packet? + if (packet_type[i] == 1) + if (packet_type[i+1] == 1) + samples += f->blocksize_1 >> 1; + else + samples += ((f->blocksize_1 - f->blocksize_0) >> 2) + (f->blocksize_0 >> 1); + else + samples += f->blocksize_0 >> 1; + } + // now, at this point, we've rewound to the very beginning of the + // _second_ packet. if we entirely discard the first packet after + // a seek, this will be exactly the right sample number. HOWEVER! + // we can't as easily compute this number for the LAST page. The + // only way to get the sample offset of the LAST page is to use + // the end loc from the previous page. But what that returns us + // is _exactly_ the place where we get our first non-overlapped + // sample. (I think. Stupid spec for being ambiguous.) So for + // consistency it's better to do that here, too. However, that + // will then require us to NOT discard all of the first frame we + // decode, in some cases, which means an even weirder frame size + // and extra code. what a fucking pain. + + // we're going to discard the first packet if we + // start the seek here, so we don't care about it. (we could actually + // do better; if the first packet is long, and the previous packet + // is short, there's actually data in the first half of the first + // packet that doesn't need discarding... but not worth paying the + // effort of tracking that of that here and in the seeking logic) + // except crap, if we infer it from the _previous_ packet's end + // location, we DO need to use that definition... and we HAVE to + // infer the start loc of the LAST packet from the previous packet's + // end location. fuck you, ogg vorbis. + + z->first_decoded_sample = z->last_decoded_sample - samples; + + // restore file state to where we were + set_file_offset(f, z->page_start); + return 1; + + // restore file state to where we were + bail: + set_file_offset(f, z->page_start); + return 0; +} + +static int vorbis_seek_frame_from_page(stb_vorbis *f, uint32 page_start, uint32 first_sample, uint32 target_sample, int fine) +{ + int left_start, left_end, right_start, right_end, mode,i; + int frame=0; + uint32 frame_start; + int frames_to_skip, data_to_skip; + + // first_sample is the sample # of the first sample that doesn't + // overlap the previous page... note that this requires us to + // _partially_ discard the first packet! bleh. + set_file_offset(f, page_start); + + f->next_seg = -1; // force page resync + + frame_start = first_sample; + // frame start is where the previous packet's last decoded sample + // was, which corresponds to left_end... EXCEPT if the previous + // packet was long and this packet is short? Probably a bug here. + + + // now, we can start decoding frames... we'll only FAKE decode them, + // until we find the frame that contains our sample; then we'll rewind, + // and try again + for (;;) { + int start; + + if (!vorbis_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) + return error(f, VORBIS_seek_failed); + + if (frame == 0) + start = left_end; + else + start = left_start; + + // the window starts at left_start; the last valid sample we generate + // before the next frame's window start is right_start-1 + if (target_sample < frame_start + right_start-start) + break; + + flush_packet(f); + if (f->eof) + return error(f, VORBIS_seek_failed); + + frame_start += right_start - start; + + ++frame; + } + + // ok, at this point, the sample we want is contained in frame #'frame' + + // to decode frame #'frame' normally, we have to decode the + // previous frame first... but if it's the FIRST frame of the page + // we can't. if it's the first frame, it means it falls in the part + // of the first frame that doesn't overlap either of the other frames. + // so, if we have to handle that case for the first frame, we might + // as well handle it for all of them, so: + if (target_sample > frame_start + (left_end - left_start)) { + // so what we want to do is go ahead and just immediately decode + // this frame, but then make it so the next get_frame_float() uses + // this already-decoded data? or do we want to go ahead and rewind, + // and leave a flag saying to skip the first N data? let's do that + frames_to_skip = frame; // if this is frame #1, skip 1 frame (#0) + data_to_skip = left_end - left_start; + } else { + // otherwise, we want to skip frames 0, 1, 2, ... frame-2 + // (which means frame-2+1 total frames) then decode frame-1, + // then leave frame pending + frames_to_skip = frame - 1; + assert(frames_to_skip >= 0); + data_to_skip = -1; + } + + set_file_offset(f, page_start); + f->next_seg = - 1; // force page resync + + for (i=0; i < frames_to_skip; ++i) { + maybe_start_packet(f); + flush_packet(f); + } + + if (data_to_skip >= 0) { + int i,j,n = f->blocksize_0 >> 1; + f->discard_samples_deferred = data_to_skip; + for (i=0; i < f->channels; ++i) + for (j=0; j < n; ++j) + f->previous_window[i][j] = 0; + f->previous_length = n; + frame_start += data_to_skip; + } else { + f->previous_length = 0; + vorbis_pump_first_frame(f); + } + + // at this point, the NEXT decoded frame will generate the desired sample + if (fine) { + // so if we're doing sample accurate streaming, we want to go ahead and decode it! + if (target_sample != frame_start) { + int n; + stb_vorbis_get_frame_float(f, &n, NULL); + assert(target_sample > frame_start); + assert(f->channel_buffer_start + (int) (target_sample-frame_start) < f->channel_buffer_end); + f->channel_buffer_start += (target_sample - frame_start); + } + } + + return 0; +} + +static int vorbis_seek_base(stb_vorbis *f, unsigned int sample_number, int fine) +{ + ProbedPage p[2],q; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + // do we know the location of the last page? + if (f->p_last.page_start == 0) { + uint32 z = stb_vorbis_stream_length_in_samples(f); + if (z == 0) return error(f, VORBIS_cant_find_last_page); + } + + p[0] = f->p_first; + p[1] = f->p_last; + + if (sample_number >= f->p_last.last_decoded_sample) + sample_number = f->p_last.last_decoded_sample-1; + + if (sample_number < f->p_first.last_decoded_sample) { + vorbis_seek_frame_from_page(f, p[0].page_start, 0, sample_number, fine); + return 0; + } else { + int attempts=0; + while (p[0].page_end < p[1].page_start) { + uint32 probe; + uint32 start_offset, end_offset; + uint32 start_sample, end_sample; + + // copy these into local variables so we can tweak them + // if any are unknown + start_offset = p[0].page_end; + end_offset = p[1].after_previous_page_start; // an address known to seek to page p[1] + start_sample = p[0].last_decoded_sample; + end_sample = p[1].last_decoded_sample; + + // currently there is no such tweaking logic needed/possible? + if (start_sample == SAMPLE_unknown || end_sample == SAMPLE_unknown) + return error(f, VORBIS_seek_failed); + + // now we want to lerp between these for the target samples... + + // step 1: we need to bias towards the page start... + if (start_offset + 4000 < end_offset) + end_offset -= 4000; + + // now compute an interpolated search loc + probe = start_offset + (int) floor((float) (end_offset - start_offset) / (end_sample - start_sample) * (sample_number - start_sample)); + + // next we need to bias towards binary search... + // code is a little wonky to allow for full 32-bit unsigned values + if (attempts >= 4) { + uint32 probe2 = start_offset + ((end_offset - start_offset) >> 1); + if (attempts >= 8) + probe = probe2; + else if (probe < probe2) + probe = probe + ((probe2 - probe) >> 1); + else + probe = probe2 + ((probe - probe2) >> 1); + } + ++attempts; + + set_file_offset(f, probe); + if (!vorbis_find_page(f, NULL, NULL)) return error(f, VORBIS_seek_failed); + if (!vorbis_analyze_page(f, &q)) return error(f, VORBIS_seek_failed); + q.after_previous_page_start = probe; + + // it's possible we've just found the last page again + if (q.page_start == p[1].page_start) { + p[1] = q; + continue; + } + + if (sample_number < q.last_decoded_sample) + p[1] = q; + else + p[0] = q; + } + + if (p[0].last_decoded_sample <= sample_number && sample_number < p[1].last_decoded_sample) { + vorbis_seek_frame_from_page(f, p[1].page_start, p[0].last_decoded_sample, sample_number, fine); + return 0; + } + return error(f, VORBIS_seek_failed); + } +} + +int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) +{ + return vorbis_seek_base(f, sample_number, FALSE); +} + +int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) +{ + return vorbis_seek_base(f, sample_number, TRUE); +} + +void stb_vorbis_seek_start(stb_vorbis *f) +{ + if (IS_PUSH_MODE(f)) { error(f, VORBIS_invalid_api_mixing); return; } + set_file_offset(f, f->first_audio_page_offset); + f->previous_length = 0; + f->first_decode = TRUE; + f->next_seg = -1; + vorbis_pump_first_frame(f); +} + +unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) +{ + unsigned int restore_offset, previous_safe; + unsigned int end, last_page_loc; + + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + if (!f->total_samples) { + unsigned int last; + uint32 lo,hi; + char header[6]; + + // first, store the current decode position so we can restore it + restore_offset = stb_vorbis_get_file_offset(f); + + // now we want to seek back 64K from the end (the last page must + // be at most a little less than 64K, but let's allow a little slop) + if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset) + previous_safe = f->stream_len - 65536; + else + previous_safe = f->first_audio_page_offset; + + set_file_offset(f, previous_safe); + // previous_safe is now our candidate 'earliest known place that seeking + // to will lead to the final page' + + if (!vorbis_find_page(f, &end, &last)) { + // if we can't find a page, we're hosed! + f->error = VORBIS_cant_find_last_page; + f->total_samples = 0xffffffff; + goto done; + } + + // check if there are more pages + last_page_loc = stb_vorbis_get_file_offset(f); + + // stop when the last_page flag is set, not when we reach eof; + // this allows us to stop short of a 'file_section' end without + // explicitly checking the length of the section + while (!last) { + set_file_offset(f, end); + if (!vorbis_find_page(f, &end, &last)) { + // the last page we found didn't have the 'last page' flag + // set. whoops! + break; + } + previous_safe = last_page_loc+1; + last_page_loc = stb_vorbis_get_file_offset(f); + } + + set_file_offset(f, last_page_loc); + + // parse the header + getn(f, (unsigned char *)header, 6); + // extract the absolute granule position + lo = get32(f); + hi = get32(f); + if (lo == 0xffffffff && hi == 0xffffffff) { + f->error = VORBIS_cant_find_last_page; + f->total_samples = SAMPLE_unknown; + goto done; + } + if (hi) + lo = 0xfffffffe; // saturate + f->total_samples = lo; + + f->p_last.page_start = last_page_loc; + f->p_last.page_end = end; + f->p_last.last_decoded_sample = lo; + f->p_last.first_decoded_sample = SAMPLE_unknown; + f->p_last.after_previous_page_start = previous_safe; + + done: + set_file_offset(f, restore_offset); + } + return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; +} + +float stb_vorbis_stream_length_in_seconds(stb_vorbis *f) +{ + return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate; +} + + + +int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) +{ + int len, right,left,i; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + f->channel_buffer_start = f->channel_buffer_end = 0; + return 0; + } + + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + f->channel_buffer_start = left; + f->channel_buffer_end = left+len; + + if (channels) *channels = f->channels; + if (output) *output = f->outputs; + return len; +} + +#ifndef STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc, unsigned int length) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.f = file; + p.f_start = ftell(file); + p.stream_len = length; + p.close_on_free = close_on_free; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc) +{ + unsigned int len, start; + start = ftell(file); + fseek(file, 0, SEEK_END); + len = ftell(file) - start; + fseek(file, start, SEEK_SET); + return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); +} + +stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorbis_alloc *alloc) +{ + FILE *f = fopen(filename, "rb"); + if (f) + return stb_vorbis_open_file(f, TRUE, error, alloc); + if (error) *error = VORBIS_file_open_failure; + return NULL; +} +#endif // STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + if (data == NULL) return NULL; + vorbis_init(&p, alloc); + p.stream = (uint8 *) data; + p.stream_end = (uint8 *) data + len; + p.stream_start = (uint8 *) p.stream; + p.stream_len = len; + p.push_mode = FALSE; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#define PLAYBACK_MONO 1 +#define PLAYBACK_LEFT 2 +#define PLAYBACK_RIGHT 4 + +#define L (PLAYBACK_LEFT | PLAYBACK_MONO) +#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO) +#define R (PLAYBACK_RIGHT | PLAYBACK_MONO) + +static int8 channel_position[7][6] = +{ + { 0 }, + { C }, + { L, R }, + { L, C, R }, + { L, R, L, R }, + { L, C, R, L, R }, + { L, C, R, L, R, C }, +}; + + +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + typedef union { + float f; + int i; + } float_conv; + typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4]; + #define FASTDEF(x) float_conv x + // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round + #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) + #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) + #define check_endianness() +#else + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) + #define check_endianness() + #define FASTDEF(x) +#endif + +static void copy_samples(short *dest, float *src, int len) +{ + int i; + check_endianness(); + for (i=0; i < len; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + dest[i] = v; + } +} + +static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) +{ + #define BUFFER_SIZE 32 + float buffer[BUFFER_SIZE]; + int i,j,o,n = BUFFER_SIZE; + check_endianness(); + for (o = 0; o < len; o += BUFFER_SIZE) { + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + if (channel_position[num_c][j] & mask) { + for (i=0; i < n; ++i) + buffer[i] += data[j][d_offset+o+i]; + } + } + for (i=0; i < n; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o+i] = v; + } + } +} + +static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) +{ + #define BUFFER_SIZE 32 + float buffer[BUFFER_SIZE]; + int i,j,o,n = BUFFER_SIZE >> 1; + // o is the offset in the source data + check_endianness(); + for (o = 0; o < len; o += BUFFER_SIZE >> 1) { + // o2 is the offset in the output data + int o2 = o << 1; + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); + if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_LEFT) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_RIGHT) { + for (i=0; i < n; ++i) { + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } + } + for (i=0; i < (n<<1); ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o2+i] = v; + } + } +} + +static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) +{ + int i; + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; + for (i=0; i < buf_c; ++i) + compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + for (i=0; i < limit; ++i) + copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples); + for ( ; i < buf_c; ++i) + memset(buffer[i]+b_offset, 0, sizeof(short) * samples); + } +} + +int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples) +{ + float **output; + int len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len > num_samples) len = num_samples; + if (len) + convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); + return len; +} + +static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len) +{ + int i; + check_endianness(); + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + assert(buf_c == 2); + for (i=0; i < buf_c; ++i) + compute_stereo_samples(buffer, data_c, data, d_offset, len); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + int j; + for (j=0; j < len; ++j) { + for (i=0; i < limit; ++i) { + FASTDEF(temp); + float f = data[i][d_offset+j]; + int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + *buffer++ = v; + } + for ( ; i < buf_c; ++i) + *buffer++ = 0; + } + } +} + +int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts) +{ + float **output; + int len; + if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts); + len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len) { + if (len*num_c > num_shorts) len = num_shorts / num_c; + convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); + } + return len; +} + +int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts) +{ + float **outputs; + int len = num_shorts / channels; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k); + buffer += k*channels; + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len) +{ + float **outputs; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +#ifndef STB_VORBIS_NO_STDIO +int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; +} +#endif // NO_STDIO + +int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + if (sample_rate) + *sample_rate = v->sample_rate; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + stb_vorbis_close(v); + return data_len; +} +#endif // STB_VORBIS_NO_INTEGER_CONVERSION + +int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats) +{ + float **outputs; + int len = num_floats / channels; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int i,j; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + for (j=0; j < k; ++j) { + for (i=0; i < z; ++i) + *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j]; + for ( ; i < channels; ++i) + *buffer++ = 0; + } + n += k; + f->channel_buffer_start += k; + if (n == len) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; +} + +int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples) +{ + float **outputs; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < num_samples) { + int i; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= num_samples) k = num_samples - n; + if (k) { + for (i=0; i < z; ++i) + memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k); + for ( ; i < channels; ++i) + memset(buffer[i]+n, 0, sizeof(float) * k); + } + n += k; + f->channel_buffer_start += k; + if (n == num_samples) + break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) + break; + } + return n; +} +#endif // STB_VORBIS_NO_PULLDATA_API + +/* Version history + 1.05 - 2015/04/19 - don't define __forceinline if it's redundant + 1.04 - 2014/08/27 - fix missing const-correct case in API + 1.03 - 2014/08/07 - Warning fixes + 1.02 - 2014/07/09 - Declare qsort compare function _cdecl on windows + 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float + 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in multichannel + (API change) report sample rate for decode-full-file funcs + 0.99996 - bracket #include for macintosh compilation by Laurent Gomila + 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem + 0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence + 0.99993 - remove assert that fired on legal files with empty tables + 0.99992 - rewind-to-start + 0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo + 0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++ + 0.9998 - add a full-decode function with a memory source + 0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition + 0.9996 - query length of vorbis stream in samples/seconds + 0.9995 - bugfix to another optimization that only happened in certain files + 0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors + 0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation + 0.9992 - performance improvement of IMDCT; now performs close to reference implementation + 0.9991 - performance improvement of IMDCT + 0.999 - (should have been 0.9990) performance improvement of IMDCT + 0.998 - no-CRT support from Casey Muratori + 0.997 - bugfixes for bugs found by Terje Mathisen + 0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen + 0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen + 0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen + 0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen + 0.992 - fixes for MinGW warning + 0.991 - turn fast-float-conversion on by default + 0.990 - fix push-mode seek recovery if you seek into the headers + 0.98b - fix to bad release of 0.98 + 0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode + 0.97 - builds under c++ (typecasting, don't use 'class' keyword) + 0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code + 0.95 - clamping code for 16-bit functions + 0.94 - not publically released + 0.93 - fixed all-zero-floor case (was decoding garbage) + 0.92 - fixed a memory leak + 0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION + 0.90 - first public release +*/ + +#endif // STB_VORBIS_HEADER_ONLY From 09e1972fed4e4b63302bd9bd12baa2c6ccf3f67c Mon Sep 17 00:00:00 2001 From: Vincent Isambart Date: Sat, 8 Aug 2015 10:45:26 +0900 Subject: [PATCH 044/522] fix clang warnings --- stb.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stb.h b/stb.h index 671ffcd..27a59bb 100644 --- a/stb.h +++ b/stb.h @@ -2973,8 +2973,8 @@ typedef struct #define stb_arr_check(a) assert(!a || stb_arrhead(a)->signature == stb_arr_signature) #define stb_arr_check2(a) assert(!a || stb_arrhead2(a)->signature == stb_arr_signature) #else -#define stb_arr_check(a) 0 -#define stb_arr_check2(a) 0 +#define stb_arr_check(a) ((void) 0) +#define stb_arr_check2(a) ((void) 0) #endif // ARRAY LENGTH @@ -3297,7 +3297,7 @@ unsigned int stb_hashptr(void *p) unsigned int stb_rehash_improved(unsigned int v) { - return stb_hashptr((void *) v); + return stb_hashptr((void *)(size_t) v); } unsigned int stb_hash2(char *str, unsigned int *hash2_ptr) @@ -10407,15 +10407,15 @@ int stb_compress_intofile(FILE *f, char *input, unsigned int length) ////////////////////// streaming I/O version ///////////////////// -static stb_uint stb_out_backpatch_id(void) +static size_t stb_out_backpatch_id(void) { if (stb__out) - return (stb_uint) stb__out; + return (size_t) stb__out; else return ftell(stb__outfile); } -static void stb_out_backpatch(stb_uint id, stb_uint value) +static void stb_out_backpatch(size_t id, stb_uint value) { stb_uchar data[4] = { value >> 24, value >> 16, value >> 8, value }; if (stb__out) { From f24f92bcc764713bc265867e741adcadb94f7000 Mon Sep 17 00:00:00 2001 From: Sergey Popov Date: Wed, 19 Aug 2015 14:36:09 +0300 Subject: [PATCH 045/522] Fix -Wextra warning in stb_truetype.h --- stb_truetype.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 5784549..9392969 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1745,7 +1745,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { - stbtt__hheap hh = { 0 }; + stbtt__hheap hh = { 0, 0, 0 }; stbtt__active_edge *active = NULL; int y,j=0; int max_weight = (255 / vsubsample); // weight per vertical scanline @@ -2047,7 +2047,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // directly AA rasterize edges w/o supersampling static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { - stbtt__hheap hh = { 0 }; + stbtt__hheap hh = { 0, 0, 0 }; stbtt__active_edge *active = NULL; int y,j=0, i; float scanline_data[129], *scanline, *scanline2; From ebb54fd7a33f900b6cb4ae0c951e4b2727ae93aa Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 30 Aug 2015 19:29:35 -0700 Subject: [PATCH 046/522] seeking in stb_vorbis (Dougall Johnson) test program for seeking (stb) --- stb_vorbis.c | 516 ++++++++++++++++-------------------- tests/stb.dsw | 14 +- tests/vorbseek/vorbseek.c | 105 ++++++++ tests/vorbseek/vorbseek.dsp | 96 +++++++ 4 files changed, 446 insertions(+), 285 deletions(-) create mode 100644 tests/vorbseek/vorbseek.c create mode 100644 tests/vorbseek/vorbseek.dsp diff --git a/stb_vorbis.c b/stb_vorbis.c index 8188724..00c61c7 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -15,18 +15,20 @@ // // Limitations: // -// - seeking not supported except manually via PUSHDATA api // - floor 0 not supported (used in old ogg vorbis files pre-2004) // - lossless sample-truncation at beginning ignored // - cannot concatenate multiple vorbis streams // - sample positions are 32-bit, limiting seekable 192Khz // files to around 6 hours (Ogg supports 64-bit) // +// Feature contributors: +// Dougall Johnson (sample-exact seeking) +// // Bugfix/warning contributors: // Terje Mathisen Niklas Frykholm Andy Hill // Casey Muratori John Bolton Gargaj // Laurent Gomila Marc LeBlanc Ronny Chevalier -// Bernhard Wodo Evan Balster "alxprd"@github +// Bernhard Wodo Evan Balster "alxprd"@github // Tom Beaumont Ingo Leitgeb Nicolas Guillemot // (If you reported a bug but do not appear in this list, it is because // someone else reported the bug before you. There were too many of you to @@ -259,7 +261,6 @@ extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_cl extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); -// NOT WORKING YET // these functions seek in the Vorbis file to (approximately) 'sample_number'. // after calling seek_frame(), the next call to get_frame_*() will include // the specified sample. after calling stb_vorbis_seek(), the next call to @@ -268,8 +269,7 @@ extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); // you can also use seek_frame(). extern void stb_vorbis_seek_start(stb_vorbis *f); -// this function is equivalent to stb_vorbis_seek(f,0), but it -// actually works +// this function is equivalent to stb_vorbis_seek(f,0) extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); @@ -714,8 +714,6 @@ typedef struct typedef struct { uint32 page_start, page_end; - uint32 after_previous_page_start; - uint32 first_decoded_sample; uint32 last_decoded_sample; } ProbedPage; @@ -1423,8 +1421,6 @@ static int start_page_no_capturepattern(vorb *f) len += 27 + f->segment_count; p.page_start = f->first_audio_page_offset; p.page_end = p.page_start + len; - p.after_previous_page_start = p.page_start; - p.first_decoded_sample = 0; p.last_decoded_sample = loc0; f->p_first = p; } @@ -4470,7 +4466,7 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) int n; if (f->eof) return 0; n = get8(f); - if (n == 0x4f) { // page header + if (n == 0x4f) { // page header candidate unsigned int retry_loc = stb_vorbis_get_file_offset(f); int i; // check if we're off the end of a file_section stream @@ -4534,37 +4530,30 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) } } -// seek is implemented with 'interpolation search'--this is like -// binary search, but we use the data values to estimate the likely -// location of the data item (plus a bit of a bias so when the -// estimation is wrong we don't waste overly much time) #define SAMPLE_unknown 0xffffffff +// seeking is implemented with a binary search, which narrows down the range to +// 64K, before using a linear search (because finding the synchronization +// pattern can be expensive, and the chance we'd find the end page again is +// relatively high for small ranges) +// +// two initial interpolation-style probes are used at the start of the search +// to try to bound either side of the binary search sensibly, while still +// working in O(log n) time if they fail. -// ogg vorbis, in its insane infinite wisdom, only provides -// information about the sample at the END of the page. -// therefore we COULD have the data we need in the current -// page, and not know it. we could just use the end location -// as our only knowledge for bounds, seek back, and eventually -// the binary search finds it. or we can try to be smart and -// not waste time trying to locate more pages. we try to be -// smart, since this data is already in memory anyway, so -// doing needless I/O would be crazy! -static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z) +static int get_seek_page_info(stb_vorbis *f, ProbedPage *z) { uint8 header[27], lacing[255]; - uint8 packet_type[255]; - int num_packet, packet_start; int i,len; - uint32 samples; // record where the page starts z->page_start = stb_vorbis_get_file_offset(f); // parse the header getn(f, header, 27); - assert(header[0] == 'O' && header[1] == 'g' && header[2] == 'g' && header[3] == 'S'); + if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S') + return 0; getn(f, lacing, header[26]); // determine the length of the payload @@ -4576,304 +4565,265 @@ static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z) z->page_end = z->page_start + 27 + header[26] + len; // read the last-decoded sample out of the data - z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 16); - - if (header[5] & 4) { - // if this is the last page, it's not possible to work - // backwards to figure out the first sample! whoops! fuck. - z->first_decoded_sample = SAMPLE_unknown; - set_file_offset(f, z->page_start); - return 1; - } - - // scan through the frames to determine the sample-count of each one... - // our goal is the sample # of the first fully-decoded sample on the - // page, which is the first decoded sample of the 2nd packet - - num_packet=0; - - packet_start = ((header[5] & 1) == 0); - - for (i=0; i < header[26]; ++i) { - if (packet_start) { - uint8 n,b; - if (lacing[i] == 0) goto bail; // trying to read from zero-length packet - n = get8(f); - // if bottom bit is non-zero, we've got corruption - if (n & 1) goto bail; - n >>= 1; - b = ilog(f->mode_count-1); - n &= (1 << b)-1; - if (n >= f->mode_count) goto bail; - packet_type[num_packet++] = f->mode_config[n].blockflag; - skip(f, lacing[i]-1); - } else - skip(f, lacing[i]); - packet_start = (lacing[i] < 255); - } - - // now that we know the sizes of all the pages, we can start determining - // how much sample data there is. - - samples = 0; - - // for the last packet, we step by its whole length, because the definition - // is that we encoded the end sample loc of the 'last packet completed', - // where 'completed' refers to packets being split, and we are left to guess - // what 'end sample loc' means. we assume it means ignoring the fact that - // the last half of the data is useless without windowing against the next - // packet... (so it's not REALLY complete in that sense) - if (num_packet > 1) - samples += f->blocksize[packet_type[num_packet-1]]; - - for (i=num_packet-2; i >= 1; --i) { - // now, for this packet, how many samples do we have that - // do not overlap the following packet? - if (packet_type[i] == 1) - if (packet_type[i+1] == 1) - samples += f->blocksize_1 >> 1; - else - samples += ((f->blocksize_1 - f->blocksize_0) >> 2) + (f->blocksize_0 >> 1); - else - samples += f->blocksize_0 >> 1; - } - // now, at this point, we've rewound to the very beginning of the - // _second_ packet. if we entirely discard the first packet after - // a seek, this will be exactly the right sample number. HOWEVER! - // we can't as easily compute this number for the LAST page. The - // only way to get the sample offset of the LAST page is to use - // the end loc from the previous page. But what that returns us - // is _exactly_ the place where we get our first non-overlapped - // sample. (I think. Stupid spec for being ambiguous.) So for - // consistency it's better to do that here, too. However, that - // will then require us to NOT discard all of the first frame we - // decode, in some cases, which means an even weirder frame size - // and extra code. what a fucking pain. - - // we're going to discard the first packet if we - // start the seek here, so we don't care about it. (we could actually - // do better; if the first packet is long, and the previous packet - // is short, there's actually data in the first half of the first - // packet that doesn't need discarding... but not worth paying the - // effort of tracking that of that here and in the seeking logic) - // except crap, if we infer it from the _previous_ packet's end - // location, we DO need to use that definition... and we HAVE to - // infer the start loc of the LAST packet from the previous packet's - // end location. fuck you, ogg vorbis. - - z->first_decoded_sample = z->last_decoded_sample - samples; + z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24); // restore file state to where we were set_file_offset(f, z->page_start); return 1; +} + +// rarely used function to seek back to the preceeding page while finding the +// start of a packet +static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset) +{ + unsigned int previous_safe, end; + + // now we want to seek back 64K from the limit + if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset) + previous_safe = limit_offset - 65536; + else + previous_safe = f->first_audio_page_offset; + + set_file_offset(f, previous_safe); + + while (vorbis_find_page(f, &end, NULL)) { + if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset) + return 1; + set_file_offset(f, end); + } - // restore file state to where we were - bail: - set_file_offset(f, z->page_start); return 0; } -static int vorbis_seek_frame_from_page(stb_vorbis *f, uint32 page_start, uint32 first_sample, uint32 target_sample, int fine) +// implements the search logic for finding a page and starting decoding. if +// the function succeeds, current_loc_valid will be true and current_loc will +// be less than or equal to the provided sample number (the closer the +// better). +static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) { - int left_start, left_end, right_start, right_end, mode,i; - int frame=0; - uint32 frame_start; - int frames_to_skip, data_to_skip; + ProbedPage left, right, mid; + int i, start_seg_with_known_loc, end_pos, page_start; + uint32 delta, stream_length, padding; + double offset, bytes_per_sample; + int probe = 0; - // first_sample is the sample # of the first sample that doesn't - // overlap the previous page... note that this requires us to - // _partially_ discard the first packet! bleh. - set_file_offset(f, page_start); + // find the last page and validate the target sample + stream_length = stb_vorbis_stream_length_in_samples(f); + if (stream_length == 0) return error(f, VORBIS_seek_without_length); + if (sample_number > stream_length) return error(f, VORBIS_seek_invalid); - f->next_seg = -1; // force page resync + // this is the maximum difference between the window-center (which is the + // actual granule position value), and the right-start (which the spec + // indicates should be the granule position (give or take one)). + padding = ((f->blocksize_1 - f->blocksize_0) >> 2); + if (sample_number < padding) + sample_number = 0; + else + sample_number -= padding; - frame_start = first_sample; - // frame start is where the previous packet's last decoded sample - // was, which corresponds to left_end... EXCEPT if the previous - // packet was long and this packet is short? Probably a bug here. + left = f->p_first; + while (left.last_decoded_sample == ~0U) { + // (untested) the first page does not have a 'last_decoded_sample' + set_file_offset(f, left.page_end); + if (!get_seek_page_info(f, &left)) goto error; + } + right = f->p_last; + assert(right.last_decoded_sample != ~0U); - // now, we can start decoding frames... we'll only FAKE decode them, - // until we find the frame that contains our sample; then we'll rewind, - // and try again - for (;;) { - int start; + // starting from the start is handled differently + if (sample_number <= left.last_decoded_sample) { + stb_vorbis_seek_start(f); + return 1; + } - if (!vorbis_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) - return error(f, VORBIS_seek_failed); + while (left.page_end != right.page_start) { + assert(left.page_end < right.page_start); + // search range in bytes + delta = right.page_start - left.page_end; + if (delta <= 65536) { + // there's only 64K left to search - handle it linearly + set_file_offset(f, left.page_end); + } else { + if (probe < 2) { + if (probe == 0) { + // first probe (interpolate) + double data_bytes = right.page_end - left.page_start; + bytes_per_sample = data_bytes / right.last_decoded_sample; + offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample); + } else { + // second probe (try to bound the other side) + double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample; + if (error >= 0 && error < 8000) error = 8000; + if (error < 0 && error > -8000) error = -8000; + offset += error * 2; + } - if (frame == 0) - start = left_end; - else - start = left_start; + // ensure the offset is valid + if (offset < left.page_end) + offset = left.page_end; + if (offset > right.page_start - 65536) + offset = right.page_start - 65536; - // the window starts at left_start; the last valid sample we generate - // before the next frame's window start is right_start-1 - if (target_sample < frame_start + right_start-start) + set_file_offset(f, (unsigned int) offset); + } else { + // binary search for large ranges (offset by 32K to ensure + // we don't hit the right page) + set_file_offset(f, left.page_end + (delta / 2) - 32768); + } + + if (!vorbis_find_page(f, NULL, NULL)) goto error; + } + + for (;;) { + if (!get_seek_page_info(f, &mid)) goto error; + if (mid.last_decoded_sample != ~0U) break; + // (untested) no frames end on this page + set_file_offset(f, mid.page_end); + assert(mid.page_start < right.page_start); + } + + // if we've just found the last page again then we're in a tricky file, + // and we're close enough. + if (mid.page_start == right.page_start) break; - flush_packet(f); - if (f->eof) - return error(f, VORBIS_seek_failed); + if (sample_number < mid.last_decoded_sample) + right = mid; + else + left = mid; - frame_start += right_start - start; - - ++frame; - } - - // ok, at this point, the sample we want is contained in frame #'frame' - - // to decode frame #'frame' normally, we have to decode the - // previous frame first... but if it's the FIRST frame of the page - // we can't. if it's the first frame, it means it falls in the part - // of the first frame that doesn't overlap either of the other frames. - // so, if we have to handle that case for the first frame, we might - // as well handle it for all of them, so: - if (target_sample > frame_start + (left_end - left_start)) { - // so what we want to do is go ahead and just immediately decode - // this frame, but then make it so the next get_frame_float() uses - // this already-decoded data? or do we want to go ahead and rewind, - // and leave a flag saying to skip the first N data? let's do that - frames_to_skip = frame; // if this is frame #1, skip 1 frame (#0) - data_to_skip = left_end - left_start; - } else { - // otherwise, we want to skip frames 0, 1, 2, ... frame-2 - // (which means frame-2+1 total frames) then decode frame-1, - // then leave frame pending - frames_to_skip = frame - 1; - assert(frames_to_skip >= 0); - data_to_skip = -1; + ++probe; } + // seek back to start of the last packet + page_start = left.page_start; set_file_offset(f, page_start); - f->next_seg = - 1; // force page resync + if (!start_page(f)) return error(f, VORBIS_seek_failed); + end_pos = f->end_seg_with_known_loc; + assert(end_pos >= 0); - for (i=0; i < frames_to_skip; ++i) { - maybe_start_packet(f); - flush_packet(f); + for (;;) { + for (i = end_pos; i > 0; --i) + if (f->segments[i-1] != 255) + break; + + start_seg_with_known_loc = i; + + if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet)) + break; + + // (untested) the final packet begins on an earlier page + if (!go_to_page_before(f, page_start)) + goto error; + + page_start = stb_vorbis_get_file_offset(f); + if (!start_page(f)) goto error; + end_pos = f->segment_count - 1; } - if (data_to_skip >= 0) { - int i,j,n = f->blocksize_0 >> 1; - f->discard_samples_deferred = data_to_skip; - for (i=0; i < f->channels; ++i) - for (j=0; j < n; ++j) - f->previous_window[i][j] = 0; - f->previous_length = n; - frame_start += data_to_skip; - } else { - f->previous_length = 0; - vorbis_pump_first_frame(f); - } + // prepare to start decoding + f->current_loc_valid = FALSE; + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + f->previous_length = 0; + f->next_seg = start_seg_with_known_loc; - // at this point, the NEXT decoded frame will generate the desired sample - if (fine) { - // so if we're doing sample accurate streaming, we want to go ahead and decode it! - if (target_sample != frame_start) { - int n; - stb_vorbis_get_frame_float(f, &n, NULL); - assert(target_sample > frame_start); - assert(f->channel_buffer_start + (int) (target_sample-frame_start) < f->channel_buffer_end); - f->channel_buffer_start += (target_sample - frame_start); - } - } + for (i = 0; i < start_seg_with_known_loc; i++) + skip(f, f->segments[i]); - return 0; + // start decoding (optimizable - this frame is generally discarded) + vorbis_pump_first_frame(f); + return 1; + +error: + // try to restore the file to a valid state + stb_vorbis_seek_start(f); + return error(f, VORBIS_seek_failed); } -static int vorbis_seek_base(stb_vorbis *f, unsigned int sample_number, int fine) +// the same as vorbis_decode_initial, but without advancing +static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) { - ProbedPage p[2],q; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + int bits_read, bytes_read; - // do we know the location of the last page? - if (f->p_last.page_start == 0) { - uint32 z = stb_vorbis_stream_length_in_samples(f); - if (z == 0) return error(f, VORBIS_cant_find_last_page); - } - - p[0] = f->p_first; - p[1] = f->p_last; - - if (sample_number >= f->p_last.last_decoded_sample) - sample_number = f->p_last.last_decoded_sample-1; - - if (sample_number < f->p_first.last_decoded_sample) { - vorbis_seek_frame_from_page(f, p[0].page_start, 0, sample_number, fine); + if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode)) return 0; - } else { - int attempts=0; - while (p[0].page_end < p[1].page_start) { - uint32 probe; - uint32 start_offset, end_offset; - uint32 start_sample, end_sample; - // copy these into local variables so we can tweak them - // if any are unknown - start_offset = p[0].page_end; - end_offset = p[1].after_previous_page_start; // an address known to seek to page p[1] - start_sample = p[0].last_decoded_sample; - end_sample = p[1].last_decoded_sample; + // either 1 or 2 bytes were read, figure out which so we can rewind + bits_read = 1 + ilog(f->mode_count-1); + if (f->mode_config[*mode].blockflag) + bits_read += 2; + bytes_read = (bits_read + 7) / 8; - // currently there is no such tweaking logic needed/possible? - if (start_sample == SAMPLE_unknown || end_sample == SAMPLE_unknown) - return error(f, VORBIS_seek_failed); + f->bytes_in_seg += bytes_read; + f->packet_bytes -= bytes_read; + skip(f, -bytes_read); + if (f->next_seg == -1) + f->next_seg = f->segment_count - 1; + else + f->next_seg--; + f->valid_bits = 0; - // now we want to lerp between these for the target samples... - - // step 1: we need to bias towards the page start... - if (start_offset + 4000 < end_offset) - end_offset -= 4000; - - // now compute an interpolated search loc - probe = start_offset + (int) floor((float) (end_offset - start_offset) / (end_sample - start_sample) * (sample_number - start_sample)); - - // next we need to bias towards binary search... - // code is a little wonky to allow for full 32-bit unsigned values - if (attempts >= 4) { - uint32 probe2 = start_offset + ((end_offset - start_offset) >> 1); - if (attempts >= 8) - probe = probe2; - else if (probe < probe2) - probe = probe + ((probe2 - probe) >> 1); - else - probe = probe2 + ((probe - probe2) >> 1); - } - ++attempts; - - set_file_offset(f, probe); - if (!vorbis_find_page(f, NULL, NULL)) return error(f, VORBIS_seek_failed); - if (!vorbis_analyze_page(f, &q)) return error(f, VORBIS_seek_failed); - q.after_previous_page_start = probe; - - // it's possible we've just found the last page again - if (q.page_start == p[1].page_start) { - p[1] = q; - continue; - } - - if (sample_number < q.last_decoded_sample) - p[1] = q; - else - p[0] = q; - } - - if (p[0].last_decoded_sample <= sample_number && sample_number < p[1].last_decoded_sample) { - vorbis_seek_frame_from_page(f, p[1].page_start, p[0].last_decoded_sample, sample_number, fine); - return 0; - } - return error(f, VORBIS_seek_failed); - } + return 1; } int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) { - return vorbis_seek_base(f, sample_number, FALSE); + uint32 max_frame_samples; + + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + // fast page-level search + if (!seek_to_sample_coarse(f, sample_number)) + return 0; + + assert(f->current_loc_valid); + assert(f->current_loc <= sample_number); + + // linear search for the relevant packet + max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2; + while (f->current_loc < sample_number) { + int left_start, left_end, right_start, right_end, mode, frame_samples; + if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) + return error(f, VORBIS_seek_failed); + // calculate the number of samples returned by the next frame + frame_samples = right_start - left_start; + if (f->current_loc + frame_samples > sample_number) { + return 1; // the next frame will contain the sample + } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) { + // there's a chance the frame after this could contain the sample + vorbis_pump_first_frame(f); + } else { + // this frame is too early to be relevant + f->current_loc += frame_samples; + f->previous_length = 0; + maybe_start_packet(f); + flush_packet(f); + } + } + // the next frame will start with the sample + assert(f->current_loc == sample_number); + return 1; } int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) { - return vorbis_seek_base(f, sample_number, TRUE); + if (!stb_vorbis_seek_frame(f, sample_number)) + return 0; + + if (sample_number != f->current_loc) { + int n; + uint32 frame_start = f->current_loc; + stb_vorbis_get_frame_float(f, &n, NULL); + assert(sample_number > frame_start); + assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end); + f->channel_buffer_start += (sample_number - frame_start); + } + + return 1; } void stb_vorbis_seek_start(stb_vorbis *f) @@ -4954,8 +4904,6 @@ unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) f->p_last.page_start = last_page_loc; f->p_last.page_end = end; f->p_last.last_decoded_sample = lo; - f->p_last.first_decoded_sample = SAMPLE_unknown; - f->p_last.after_previous_page_start = previous_safe; done: set_file_offset(f, restore_offset); diff --git a/tests/stb.dsw b/tests/stb.dsw index c8d1388..5e5a120 100644 --- a/tests/stb.dsw +++ b/tests/stb.dsw @@ -63,7 +63,7 @@ Package=<4> ############################################################################### -Project: "resize"=.\resize\resize.dsp - Package Owner=<4> +Project: "resize"=.\resize.dsp - Package Owner=<4> Package=<5> {{{ @@ -123,6 +123,18 @@ Package=<4> ############################################################################### +Project: "vorbseek"=.\vorbseek\vorbseek.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Global: Package=<5> diff --git a/tests/vorbseek/vorbseek.c b/tests/vorbseek/vorbseek.c new file mode 100644 index 0000000..d9d4003 --- /dev/null +++ b/tests/vorbseek/vorbseek.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +#define STB_VORBIS_HEADER_ONLY +#include "stb_vorbis.c" + +#define SAMPLES_TO_TEST 3000 + +int test_count [5] = { 5000, 3000, 2000, 50000, 50000 }; +int test_spacing[5] = { 1, 111, 3337, 7779, 72717 }; + +int try_seeking(stb_vorbis *v, unsigned int pos, short *output, unsigned int num_samples) +{ + int count; + short samples[SAMPLES_TO_TEST*2]; + assert(pos <= num_samples); + + if (!stb_vorbis_seek(v, pos)) { + fprintf(stderr, "Seek to %u returned error from stb_vorbis\n", pos); + return 0; + } + + count = stb_vorbis_get_samples_short_interleaved(v, 2, samples, SAMPLES_TO_TEST*2); + + if (count > (int) (num_samples - pos)) { + fprintf(stderr, "Seek to %u allowed decoding %d samples when only %d should have been valid.\n", + pos, count, (int) (num_samples - pos)); + return 0; + } + + if (count < SAMPLES_TO_TEST && count < (int) (num_samples - pos)) { + fprintf(stderr, "Seek to %u only decoded %d samples of %d attempted when at least %d should have been valid.\n", + pos, count, SAMPLES_TO_TEST, num_samples - pos); + return 0; + } + + if (0 != memcmp(samples, output + pos*2, count*2)) { + int k; + for (k=0; k < SAMPLES_TO_TEST*2; ++k) { + if (samples[k] != output[k]) { + fprintf(stderr, "Seek to %u produced incorrect samples starting at sample %u (short #%d in buffer).\n", + pos, pos + (k/2), k); + break; + } + } + assert(k != SAMPLES_TO_TEST*2); + return 0; + } + + return 1; +} + +int main(int argc, char **argv) +{ + int num_chan, samprate; + int i, j, test, phase; + short *output; + if (argc == 1) { + fprintf(stderr, "Usage: vorbseek {vorbisfile} [{vorbisfile]*]\n"); + fprintf(stderr, "Tests various seek offsets to make sure they're sample exact.\n"); + return 0; + } + + for (j=1; j < argc; ++j) { + unsigned int successes=0, attempts = 0; + unsigned int num_samples = stb_vorbis_decode_filename(argv[j], &num_chan, &samprate, &output); + + if (num_samples == 0xffffffff) { + fprintf(stderr, "Error: couldn't open file or not vorbis file: %s\n", argv[j]); + goto fail; + } + + if (num_chan != 2) { + fprintf(stderr, "vorbseek testing only works with files with 2 channels, %s has %d\n", argv[j], num_chan); + goto fail; + } + + for (test=0; test < 5; ++test) { + int error; + stb_vorbis *v = stb_vorbis_open_filename(argv[j], &error, NULL); + if (v == NULL) { + fprintf(stderr, "Couldn't re-open %s for test #%d\n", argv[j], test); + goto fail; + } + for (phase=0; phase < 3; ++phase) { + unsigned int base = phase == 0 ? 0 : phase == 1 ? num_samples - test_count[test]*test_spacing[test] : num_samples/3; + for (i=0; i < test_count[test]; ++i) { + unsigned int pos = base + i*test_spacing[test]; + if (pos > num_samples) // this also catches underflows + continue; + successes += try_seeking(v, pos, output, num_samples); + attempts += 1; + } + } + stb_vorbis_close(v); + } + printf("%d of %d seeks failed in %s (%d samples)\n", attempts-successes, attempts, argv[j], num_samples); + free(output); + } + return 0; + fail: + return 1; +} \ No newline at end of file diff --git a/tests/vorbseek/vorbseek.dsp b/tests/vorbseek/vorbseek.dsp new file mode 100644 index 0000000..5e7b09f --- /dev/null +++ b/tests/vorbseek/vorbseek.dsp @@ -0,0 +1,96 @@ +# Microsoft Developer Studio Project File - Name="vorbseek" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=vorbseek - 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 "vorbseek.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 "vorbseek.mak" CFG="vorbseek - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "vorbseek - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "vorbseek - 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)" == "vorbseek - 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)" == "vorbseek - 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 "vorbseek - Win32 Release" +# Name "vorbseek - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project From c15190373c9a40ef7a7e6cad4f8324ec14bf8bf4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 30 Aug 2015 19:31:36 -0700 Subject: [PATCH 047/522] add missing changes to project file --- tests/vorbseek/vorbseek.dsp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/vorbseek/vorbseek.dsp b/tests/vorbseek/vorbseek.dsp index 5e7b09f..5eaf579 100644 --- a/tests/vorbseek/vorbseek.dsp +++ b/tests/vorbseek/vorbseek.dsp @@ -39,9 +39,11 @@ RSC=rc.exe # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 # 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 CPP /nologo /W3 /GX /Zd /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -49,7 +51,7 @@ BSC32=bscmake.exe # 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 +# 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 !ELSEIF "$(CFG)" == "vorbseek - Win32 Debug" @@ -62,9 +64,11 @@ LINK32=link.exe # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 # 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 CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /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 @@ -80,17 +84,13 @@ LINK32=link.exe # Name "vorbseek - Win32 Release" # Name "vorbseek - Win32 Debug" -# Begin Group "Source Files" +# Begin Source File -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# End Group -# Begin Group "Header Files" +SOURCE=..\..\stb_vorbis.c +# End Source File +# Begin Source File -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group +SOURCE=.\vorbseek.c +# End Source File # End Target # End Project From a009673856f0de13d5af47654d28e03e07f8f128 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 31 Aug 2015 12:49:03 -0700 Subject: [PATCH 048/522] update stb_vorbis version --- stb_vorbis.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 00c61c7..2dfb126 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.05 - public domain +// Ogg Vorbis audio decoder - v1.06 - public domain // http://nothings.org/stb_vorbis/ // // Written by Sean Barrett in 2007, last updated in 2014 @@ -35,6 +35,7 @@ // list them all because I was lax about updating for a long time, sorry.) // // Partial history: +// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) // 1.05 - 2015/04/19 - don't define __forceinline if it's redundant // 1.04 - 2014/08/27 - fix missing const-correct case in API // 1.03 - 2014/08/07 - warning fixes From 0e24ec5feb2e1ac70bb35c25faa1fa4b8b7cda3f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 3 Sep 2015 07:11:02 -0700 Subject: [PATCH 049/522] fix some cases that didn't return outofmem error properly and would crash instead --- stb_vorbis.c | 43 ++++++++++++++++++++++++++++----------- tests/vorbseek/vorbseek.c | 18 ++++++++++++++++ 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 2dfb126..57cb825 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3739,6 +3739,7 @@ static int start_decoder(vorb *f) f->setup_temp_memory_required = c->entries; c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem); memcpy(c->codeword_lengths, lengths, c->entries); setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! lengths = c->codeword_lengths; @@ -3786,10 +3787,13 @@ static int start_decoder(vorb *f) if (c->sorted_entries) { // allocate an extra slot for sentinels c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); + if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem); // allocate an extra slot at the front so that c->sorted_values[-1] is defined // so that we can catch that case without an extra if c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); - if (c->sorted_values) { ++c->sorted_values; c->sorted_values[-1] = -1; } + if (c->sorted_values == NULL) return error(f, VORBIS_outofmem); + ++c->sorted_values; + c->sorted_values[-1] = -1; compute_sorted_huffman(c, lengths, values); } @@ -3859,6 +3863,7 @@ static int start_decoder(vorb *f) #endif { c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); + if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } #ifndef STB_VORBIS_CODEBOOK_FLOATS memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values); #else @@ -3892,6 +3897,7 @@ static int start_decoder(vorb *f) // Floors f->floor_count = get_bits(f, 6)+1; f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); + if (f->floor_config == NULL) return error(f, VORBIS_outofmem); for (i=0; i < f->floor_count; ++i) { f->floor_types[i] = get_bits(f, 16); if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); @@ -3963,7 +3969,9 @@ static int start_decoder(vorb *f) // Residue f->residue_count = get_bits(f, 6)+1; - f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(*f->residue_config)); + f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0])); + if (f->residue_config == NULL) return error(f, VORBIS_outofmem); + memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0])); for (i=0; i < f->residue_count; ++i) { uint8 residue_cascade[64]; Residue *r = f->residue_config+i; @@ -3982,6 +3990,7 @@ static int start_decoder(vorb *f) residue_cascade[j] = high_bits*8 + low_bits; } r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); + if (r->residue_books == NULL) return error(f, VORBIS_outofmem); for (j=0; j < r->classifications; ++j) { for (k=0; k < 8; ++k) { if (residue_cascade[j] & (1 << k)) { @@ -4001,6 +4010,7 @@ static int start_decoder(vorb *f) int classwords = f->codebooks[r->classbook].dimensions; int temp = j; r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); + if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem); for (k=classwords-1; k >= 0; --k) { r->classdata[j][k] = temp % r->classifications; temp /= r->classifications; @@ -4010,11 +4020,14 @@ static int start_decoder(vorb *f) f->mapping_count = get_bits(f,6)+1; f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); + if (f->mapping == NULL) return error(f, VORBIS_outofmem); + memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); for (i=0; i < f->mapping_count; ++i) { Mapping *m = f->mapping + i; int mapping_type = get_bits(f,16); if (mapping_type != 0) return error(f, VORBIS_invalid_setup); m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); + if (m->chan == NULL) return error(f, VORBIS_outofmem); if (get_bits(f,1)) m->submaps = get_bits(f,4)+1; else @@ -4075,8 +4088,10 @@ static int start_decoder(vorb *f) f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); + if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem); #ifdef STB_VORBIS_NO_DEFER_FLOOR f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem); #endif } @@ -4134,14 +4149,16 @@ static int start_decoder(vorb *f) static void vorbis_deinit(stb_vorbis *p) { int i,j; - for (i=0; i < p->residue_count; ++i) { - Residue *r = p->residue_config+i; - if (r->classdata) { - for (j=0; j < p->codebooks[r->classbook].entries; ++j) - setup_free(p, r->classdata[j]); - setup_free(p, r->classdata); + if (p->residue_config) { + for (i=0; i < p->residue_count; ++i) { + Residue *r = p->residue_config+i; + if (r->classdata) { + for (j=0; j < p->codebooks[r->classbook].entries; ++j) + setup_free(p, r->classdata[j]); + setup_free(p, r->classdata); + } + setup_free(p, r->residue_books); } - setup_free(p, r->residue_books); } if (p->codebooks) { @@ -4158,9 +4175,11 @@ static void vorbis_deinit(stb_vorbis *p) } setup_free(p, p->floor_config); setup_free(p, p->residue_config); - for (i=0; i < p->mapping_count; ++i) - setup_free(p, p->mapping[i].chan); - setup_free(p, p->mapping); + if (p->mapping) { + for (i=0; i < p->mapping_count; ++i) + setup_free(p, p->mapping[i].chan); + setup_free(p, p->mapping); + } for (i=0; i < p->channels; ++i) { setup_free(p, p->channel_buffers[i]); setup_free(p, p->previous_window[i]); diff --git a/tests/vorbseek/vorbseek.c b/tests/vorbseek/vorbseek.c index d9d4003..d51ed4f 100644 --- a/tests/vorbseek/vorbseek.c +++ b/tests/vorbseek/vorbseek.c @@ -57,12 +57,30 @@ int main(int argc, char **argv) int num_chan, samprate; int i, j, test, phase; short *output; + if (argc == 1) { fprintf(stderr, "Usage: vorbseek {vorbisfile} [{vorbisfile]*]\n"); fprintf(stderr, "Tests various seek offsets to make sure they're sample exact.\n"); return 0; } + #if 0 + { + // check that outofmem occurs correctly + stb_vorbis_alloc va; + va.alloc_buffer = malloc(1024*1024); + for (i=0; i < 1024*1024; i += 10) { + int error=0; + stb_vorbis *v; + va.alloc_buffer_length_in_bytes = i; + v = stb_vorbis_open_filename(argv[1], &error, &va); + if (v != NULL) + break; + printf("Error %d at %d\n", error, i); + } + } + #endif + for (j=1; j < argc; ++j) { unsigned int successes=0, attempts = 0; unsigned int num_samples = stb_vorbis_decode_filename(argv[j], &num_chan, &samprate, &output); From 76706563229f13370be2265d31fa853e75bdbc2e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 3 Sep 2015 10:24:01 -0700 Subject: [PATCH 050/522] fix some signed shifts that should have been unsigned for C spec reasons --- stb_vorbis.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 57cb825..07385e6 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -36,6 +36,8 @@ // // Partial history: // 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) +// some crash fixes when out of memory or with corrupt files +// fix some inappropriately signed shifts // 1.05 - 2015/04/19 - don't define __forceinline if it's redundant // 1.04 - 2014/08/27 - fix missing const-correct case in API // 1.03 - 2014/08/07 - warning fixes @@ -934,7 +936,7 @@ static void crc32_init(void) int i,j; uint32 s; for(i=0; i < 256; i++) { - for (s=i<<24, j=0; j < 8; ++j) + for (s=(uint32) i << 24, j=0; j < 8; ++j) s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); crc_table[i] = s; } @@ -1035,7 +1037,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) add_entry(c, 0, k, m++, len[k], values); // add all available leaves for (i=1; i <= len[k]; ++i) - available[i] = 1 << (32-i); + available[i] = 1U << (32-i); // note that the above code treats the first case specially, // but it's really the same as the following code, so they // could probably be combined (except the initial code is 0, @@ -1564,7 +1566,7 @@ static __forceinline void prep_huffman(vorb *f) if (f->last_seg && !f->bytes_in_seg) return; z = get8_packet_raw(f); if (z == EOP) return; - f->acc += z << f->valid_bits; + f->acc += (unsigned) z << f->valid_bits; f->valid_bits += 8; } while (f->valid_bits <= 24); } @@ -5383,6 +5385,8 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) + some crash fixes when out of memory or with corrupt files 1.05 - 2015/04/19 - don't define __forceinline if it's redundant 1.04 - 2014/08/27 - fix missing const-correct case in API 1.03 - 2014/08/07 - Warning fixes From a3d62dfec1153b56f657e5d8f7e43b13f12f0ab2 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 3 Sep 2015 11:16:19 -0700 Subject: [PATCH 051/522] fix a few crash bugs with invalid stb_vorbis files (reported by Philip Bennefall, found using a fuzz tester) --- stb_vorbis.c | 19 +++++++++++++------ tests/vorbseek/vorbseek.c | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 07385e6..8a549d6 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1053,7 +1053,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) // trivial to prove, but it seems true and the assert never // fires, so! while (z > 0 && !available[z]) --z; - if (z == 0) { assert(0); return FALSE; } + if (z == 0) { return FALSE; } res = available[z]; available[z] = 0; add_entry(c, bit_reverse(res), i, m++, len[i], values); @@ -3138,7 +3138,8 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f { int hy = finalY[j] * g->floor1_multiplier; int hx = g->Xlist[j]; - draw_line(target, lx,ly, hx,hy, n2); + if (lx != hx) + draw_line(target, lx,ly, hx,hy, n2); lx = hx, ly = hy; } } @@ -3430,9 +3431,15 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, f->current_loc_valid = TRUE; f->first_decode = FALSE; } else if (f->discard_samples_deferred) { - left_start += f->discard_samples_deferred; - *p_left = left_start; - f->discard_samples_deferred = 0; + if (f->discard_samples_deferred >= right_start - left_start) { + f->discard_samples_deferred -= (right_start - left_start); + left_start = right_start; + *p_left = left_start; + } else { + left_start += f->discard_samples_deferred; + *p_left = left_start; + f->discard_samples_deferred = 0; + } } else if (f->previous_length == 0 && f->current_loc_valid) { // we're recovering from a seek... that means we're going to discard // the samples from this packet even though we know our position from @@ -4182,7 +4189,7 @@ static void vorbis_deinit(stb_vorbis *p) setup_free(p, p->mapping[i].chan); setup_free(p, p->mapping); } - for (i=0; i < p->channels; ++i) { + for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) { setup_free(p, p->channel_buffers[i]); setup_free(p, p->previous_window[i]); #ifdef STB_VORBIS_NO_DEFER_FLOOR diff --git a/tests/vorbseek/vorbseek.c b/tests/vorbseek/vorbseek.c index d51ed4f..f3460ad 100644 --- a/tests/vorbseek/vorbseek.c +++ b/tests/vorbseek/vorbseek.c @@ -85,6 +85,8 @@ int main(int argc, char **argv) unsigned int successes=0, attempts = 0; unsigned int num_samples = stb_vorbis_decode_filename(argv[j], &num_chan, &samprate, &output); + break; + if (num_samples == 0xffffffff) { fprintf(stderr, "Error: couldn't open file or not vorbis file: %s\n", argv[j]); goto fail; From 60939ec6536ecf85ec30e304e31d85c33dbf8787 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 3 Sep 2015 11:18:40 -0700 Subject: [PATCH 052/522] fix some more signed shifts --- stb_image.h | 2 +- stb_vorbis.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 55edc3e..67d2981 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3544,7 +3544,7 @@ static void stbi__fill_bits(stbi__zbuf *z) { do { STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); - z->code_buffer |= stbi__zget8(z) << z->num_bits; + z->code_buffer |= (usigned int) stbi__zget8(z) << z->num_bits; z->num_bits += 8; } while (z->num_bits <= 24); } diff --git a/stb_vorbis.c b/stb_vorbis.c index 8a549d6..98e96fb 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1293,7 +1293,7 @@ static uint32 get32(vorb *f) x = get8(f); x += get8(f) << 8; x += get8(f) << 16; - x += get8(f) << 24; + x += (uint32) get8(f) << 24; return x; } From 4743a1a6e60c61bf25e3483688f0205118134972 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 3 Sep 2015 11:20:24 -0700 Subject: [PATCH 053/522] update stb_vorbis --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ea743fa..e485d67 100644 --- a/README.md +++ b/README.md @@ -7,27 +7,27 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**stb_vorbis.c** | 1.05 | audio | 5459 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.06 | graphics | 6437 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_vorbis.c** | 1.06 | audio | 5441 | decode ogg vorbis files from file/memory to float/16-bit signed output +**stb_image.h** | 2.06 | graphics | 6438 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **stb_truetype.h** | 1.07 | graphics | 3220 | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 0.98 | graphics | 730 | image writing to disk: PNG, TGA, BMP -**stb_image_resize.h** | 0.90 | graphics | 2585 | resize images larger/smaller with good quality -**stb_rect_pack.h** | 0.06 | graphics | 560 | simple 2D rectangle packer with decent quality -**stretchy_buffer.h** | 1.02 | utility | 210 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ +**stb_image_write.h** | 0.98 | graphics | 735 | image writing to disk: PNG, TGA, BMP +**stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality +**stb_rect_pack.h** | 0.06 | graphics | 566 | simple 2D rectangle packer with decent quality +**stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **stb_textedit.h** | 1.6 | UI | 1290 | guts of a text editor for games etc implementing them from scratch -**stb_voxel_render.h** | 0.82 | 3D graphics | 3739 | Minecraft-esque voxel rendering "engine" with many more features -**stb_dxt.h** | 1.04 | 3D graphics | 624 | Fabian "ryg" Giesen's real-time DXT compressor -**stb_perlin.h** | 0.2 | 3D graphics | 175 | revised Perlin noise (3D input, 1D output) -**stb_easy_font.h** | 0.5 | 3D graphics | 220 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc +**stb_voxel_render.h** | 0.82 | 3D graphics | 3746 | Minecraft-esque voxel rendering "engine" with many more features +**stb_dxt.h** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor +**stb_perlin.h** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) +**stb_easy_font.h** | 0.5 | 3D graphics | 226 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **stb_tilemap_editor.h** | 0.35 | game dev | 4120 | embeddable tilemap editor -**stb_herringbone_wa...** | 0.6 | game dev | 1217 | herringbone Wang tile map generator -**stb_c_lexer.h** | 0.06 | parsing | 809 | simplify writing parsers for C-like languages -**stb_divide.h** | 0.91 | math | 373 | more useful 32-bit modulus e.g. "euclidean divide" -**stb.h** | 2.24 | misc | 14086 | helper functions for C, mostly redundant in C++; basically author's personal stuff -**stb_leakcheck.h** | 0.2 | misc | 117 | quick-and-dirty malloc/free leak-checking +**stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator +**stb_c_lexer.h** | 0.06 | parsing | 815 | simplify writing parsers for C-like languages +**stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" +**stb.h** | 2.24 | misc | 14093 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**stb_leakcheck.h** | 0.2 | misc | 122 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 45971 +Total lines of C code: 46025 FAQ From 7ac0f9c9b0cc72549f85716b1c3dcd178b4f668d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 3 Sep 2015 22:55:01 -0700 Subject: [PATCH 054/522] fix typo in accidentally-checked-in stb_image.h --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 67d2981..b9b265f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3544,7 +3544,7 @@ static void stbi__fill_bits(stbi__zbuf *z) { do { STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); - z->code_buffer |= (usigned int) stbi__zget8(z) << z->num_bits; + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; z->num_bits += 8; } while (z->num_bits <= 24); } From 6d613ed8ce46f1f142a9ecbc341423655140f2ee Mon Sep 17 00:00:00 2001 From: Nathan Reed Date: Thu, 10 Sep 2015 01:13:54 -0700 Subject: [PATCH 055/522] Fix variable-shadowing warnings that appear in VS2015 on /W4 --- stb_image.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/stb_image.h b/stb_image.h index b9b265f..cf124eb 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3502,7 +3502,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) z->size [c] = (stbi_uc ) s; z->value[c] = (stbi__uint16) i; if (s <= STBI__ZFAST_BITS) { - int k = stbi__bit_reverse(next_code[s],s); + k = stbi__bit_reverse(next_code[s],s); while (k < (1 << STBI__ZFAST_BITS)) { z->fast[k] = fastv; k += (1 << s); @@ -4111,8 +4111,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r } if (img_n != out_n) { // insert alpha = 255 - stbi_uc *cur = a->out + stride*j; - int i; + cur = a->out + stride*j; if (img_n == 1) { for (i=x-1; i >= 0; --i) { cur[i*2+1] = 255; @@ -4909,8 +4908,8 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int if ( !tga_indexed && !tga_is_RLE) { for (i=0; i < tga_height; ++i) { - int y = tga_inverted ? tga_height -i - 1 : i; - stbi_uc *tga_row = tga_data + y*tga_width*tga_comp; + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; stbi__getn(s, tga_row, tga_width * tga_comp); } } else { @@ -5351,7 +5350,6 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c if (count >= 128) { // Repeated stbi_uc value[4]; - int i; if (count==128) count = stbi__get16be(s); @@ -5593,7 +5591,7 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) bits |= (stbi__int32) stbi__get8(s) << valid_bits; valid_bits += 8; } else { - stbi__int32 code = bits & codemask; + code = bits & codemask; bits >>= codesize; valid_bits -= codesize; // @OPTIMIZE: is there some way we can accelerate the non-clear path? From 26c98260b66b36c5256f9e51aabaad49220bd5d0 Mon Sep 17 00:00:00 2001 From: Nathan Reed Date: Thu, 10 Sep 2015 01:20:35 -0700 Subject: [PATCH 056/522] Fix warnings about "conversion to a greater size" that appear in VS2015 in x64 with /W4. The warning concerns the return value of stbi_err, which is an int, being converted to a pointer. In VS2015 it seems casting directly from a 32-bit int to a 64-bit pointer triggers this warning. Worked around by first converting to a 64-bit int (here size_t) and then to a pointer. --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index cf124eb..a301fd4 100644 --- a/stb_image.h +++ b/stb_image.h @@ -902,8 +902,8 @@ static void *stbi__malloc(size_t size) #define stbi__err(x,y) stbi__err(x) #endif -#define stbi__errpf(x,y) ((float *) (stbi__err(x,y)?NULL:NULL)) -#define stbi__errpuc(x,y) ((unsigned char *) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) STBIDEF void stbi_image_free(void *retval_from_stbi_load) { From b0d162d8294d222ff64dd7bcaf49c5a6f548d953 Mon Sep 17 00:00:00 2001 From: James Hofmann Date: Sat, 12 Sep 2015 05:45:39 -0700 Subject: [PATCH 057/522] DMC doesn't accept struct initializer syntax It expects constants. The long way compiles (but I haven't actually called this function yet) --- stb_voxel_render.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index b8ab3ba..75f32f7 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -3382,7 +3382,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po static void stbvox_make_mesh_for_column(stbvox_mesh_maker *mm, int x, int y, int z0) { - stbvox_pos pos = { x,y,0 }; + stbvox_pos pos; pos.x = x; pos.y = y; pos.z = 0; int v_off = x * mm->x_stride_in_bytes + y * mm->y_stride_in_bytes; int ns_off = mm->y_stride_in_bytes; int ew_off = mm->x_stride_in_bytes; From 6a45a88e0ff1c33deb95a9108bf118c878705094 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 04:14:02 -0700 Subject: [PATCH 058/522] update "DMC doesn't accept struct initializer" patch to be VC6 compliant --- stb_voxel_render.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 75f32f7..33021df 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -3382,10 +3382,13 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po static void stbvox_make_mesh_for_column(stbvox_mesh_maker *mm, int x, int y, int z0) { - stbvox_pos pos; pos.x = x; pos.y = y; pos.z = 0; + stbvox_pos pos; int v_off = x * mm->x_stride_in_bytes + y * mm->y_stride_in_bytes; int ns_off = mm->y_stride_in_bytes; int ew_off = mm->x_stride_in_bytes; + pos.x = x; + pos.y = y; + pos.z = 0; if (mm->input.geometry) { unsigned char *bt = mm->input.blocktype + v_off; unsigned char *geo = mm->input.geometry + v_off; From 6fe9dae224d201f3f38390a0dd39a6b6b50445fa Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 04:19:17 -0700 Subject: [PATCH 059/522] bump stb_voxel_render version number --- stb_voxel_render.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 33021df..bf3d30c 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -1,4 +1,4 @@ -// stb_voxel_render.h - v0.82 - Sean Barrett, 2015 - public domain +// stb_voxel_render.h - v0.83 - Sean Barrett, 2015 - public domain // // This library helps render large-scale "voxel" worlds for games, // in this case, one with blocks that can have textures and that @@ -190,6 +190,7 @@ // // VERSION HISTORY // +// 0.83 (2015-09-13) remove non-constant struct initializers to support more compilers // 0.82 (2015-08-01) added input.packed_compact to store rot, vheight & texlerp efficiently // fix broken tex_overlay2 // 0.81 (2015-05-28) fix broken STBVOX_CONFIG_OPTIMIZED_VHEIGHT From 9c3e9d63ea700cec6b88df3ea32404050d0d7d4e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 04:20:00 -0700 Subject: [PATCH 060/522] add to contributor list --- stb_voxel_render.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index bf3d30c..9a06a2b 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -186,7 +186,7 @@ // Features Porting Bugfixes & Warnings // Sean Barrett github:r-leyh Jesus Fernandez // Miguel Lechon github:Arbeiterunfallversicherungsgesetz -// Thomas Frase +// Thomas Frase James Hoffman // // VERSION HISTORY // From fee80f3d83c5600a6c2b58d4940a46ac57cd22fa Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 04:27:24 -0700 Subject: [PATCH 061/522] tweaks to patch from reedbeta --- stb_image.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/stb_image.h b/stb_image.h index a301fd4..494b5e5 100644 --- a/stb_image.h +++ b/stb_image.h @@ -143,6 +143,7 @@ Latest revision history: + 2.07 (2015-09-13) fix compiler warnings 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit @@ -203,6 +204,7 @@ Martins Mozeiko Joseph Thomson Phil Jordan + Nathan Reed LICENSE @@ -3502,10 +3504,10 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) z->size [c] = (stbi_uc ) s; z->value[c] = (stbi__uint16) i; if (s <= STBI__ZFAST_BITS) { - k = stbi__bit_reverse(next_code[s],s); - while (k < (1 << STBI__ZFAST_BITS)) { - z->fast[k] = fastv; - k += (1 << s); + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); } } ++next_code[s]; @@ -5556,7 +5558,7 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) { stbi_uc lzw_cs; - stbi__int32 len, code; + stbi__int32 len, init_code; stbi__uint32 first; stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; stbi__gif_lzw *p; @@ -5569,10 +5571,10 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) codemask = (1 << codesize) - 1; bits = 0; valid_bits = 0; - for (code = 0; code < clear; code++) { - g->codes[code].prefix = -1; - g->codes[code].first = (stbi_uc) code; - g->codes[code].suffix = (stbi_uc) code; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; } // support no starting clear code @@ -5591,7 +5593,7 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) bits |= (stbi__int32) stbi__get8(s) << valid_bits; valid_bits += 8; } else { - code = bits & codemask; + stbi__int32 code = bits & codemask; bits >>= codesize; valid_bits -= codesize; // @OPTIMIZE: is there some way we can accelerate the non-clear path? From 52d400741c93a3638b3fbc133fad4eaa5796d7fc Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 04:46:50 -0700 Subject: [PATCH 062/522] detect all 0-alpha bmp and replace with all-255; fix bug in reedbeta patch --- stb_image.h | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/stb_image.h b/stb_image.h index 494b5e5..b0a9073 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.06 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.08 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -205,6 +205,7 @@ Joseph Thomson Phil Jordan Nathan Reed + urraka@github LICENSE @@ -4112,20 +4113,21 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); } if (img_n != out_n) { + int q; // insert alpha = 255 cur = a->out + stride*j; if (img_n == 1) { - for (i=x-1; i >= 0; --i) { - cur[i*2+1] = 255; - cur[i*2+0] = cur[i]; + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; } } else { STBI_ASSERT(img_n == 3); - for (i=x-1; i >= 0; --i) { - cur[i*4+3] = 255; - cur[i*4+2] = cur[i*3+2]; - cur[i*4+1] = cur[i*3+1]; - cur[i*4+0] = cur[i*3+0]; + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; } } } @@ -4580,7 +4582,7 @@ static int stbi__shiftsigned(int v, int shift, int bits) static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi_uc *out; - unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a=255; stbi_uc pal[256][4]; int psize=0,i,j,compress=0,width; int bpp, flip_vertically, pad, target, offset, hsz; @@ -4629,8 +4631,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int mg = 0xffu << 8; mb = 0xffu << 0; ma = 0xffu << 24; - fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 - STBI_NOTUSED(fake_a); + all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 } else { mr = 31u << 10; mg = 31u << 5; @@ -4741,6 +4742,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int out[z+0] = stbi__get8(s); z += 3; a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; if (target == 4) out[z++] = a; } } else { @@ -4751,12 +4753,19 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; if (target == 4) out[z++] = STBI__BYTECAST(a); } } stbi__skip(s, pad); } } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + if (flip_vertically) { stbi_uc t; for (j=0; j < (int) s->img_y>>1; ++j) { From 5607c25cf49f65fa43bd204b29ee83fb30e679dc Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 05:11:51 -0700 Subject: [PATCH 063/522] tweak rmitton 16-bit psd patch; adjust credits --- stb_image.h | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/stb_image.h b/stb_image.h index 5f384e5..030a8e2 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.08 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.07 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -25,13 +25,16 @@ TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE - PSD (composited view only, no extra channels) + PSD (composited view only, no extra channels, 8/16 bit-per-channel) GIF (*comp always reports as 4-channel) HDR (radiance rgbE format) PIC (Softimage PIC) PNM (PPM and PGM binary only) + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) - decode from arbitrary I/O callbacks - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) @@ -143,7 +146,8 @@ Latest revision history: - 2.07 (2015-09-13) fix compiler warnings + 2.07 (2015-09-13) fix compiler warnings; animated GIF support close; + limited 16-bit PSD support 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit @@ -177,35 +181,34 @@ Tom Seddon (pic) the Horde3D community Thatcher Ulrich (psd) Janez Zemva Ken Miller (pgm, ppm) Jonathan Blow - Laurent Gomila + urraka@github (animated gif) Laurent Gomila Aruelien Pocheville - Extensions, features Ryamond Barbiero - Jetro Lauha (stbi_info) David Woo - Martin "SpartanJ" Golini (stbi_info) Martin Golini - James "moose2000" Brown (iPhone PNG) Roy Eltham - Ben "Disch" Wenger (io callbacks) Luke Graham - Omar Cornut (1/2/4-bit PNG) Thomas Ruf - Nicolas Guillemot (vertical flip) John Bartholomew - Ken Hamada - Optimizations & bugfixes Cort Stratton - Fabian "ryg" Giesen Blazej Dariusz Roszkowski - Arseny Kapoulkine Thibault Reuille + Ryamond Barbiero + David Woo + Extensions, features Martin Golini + Jetro Lauha (stbi_info) Roy Eltham + Martin "SpartanJ" Golini (stbi_info) Luke Graham + James "moose2000" Brown (iPhone PNG) Thomas Ruf + Ben "Disch" Wenger (io callbacks) John Bartholomew + Omar Cornut (1/2/4-bit PNG) Ken Hamada + Nicolas Guillemot (vertical flip) Cort Stratton + Richard Mitton (16-bit PSD) Blazej Dariusz Roszkowski + Thibault Reuille Paul Du Bois Guillaume George - If your name should be here but Jerry Jansson - isn't, let Sean know. Hayaki Saito + Jerry Jansson + Hayaki Saito Johan Duparc Ronny Chevalier - Michal Cichon - Tero Hanninen - Sergio Gonzalez + Optimizations & bugfixes Michal Cichon + Fabian "ryg" Giesen Tero Hanninen + Arseny Kapoulkine Sergio Gonzalez Cass Everitt Engin Manap - Martins Mozeiko - Joseph Thomson + If your name should be here but Martins Mozeiko + isn't, let Sean know. Joseph Thomson Phil Jordan Nathan Reed - urraka@github LICENSE @@ -5206,7 +5209,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int // Read the data. if (bitdepth == 16) { for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get16be(s) * 255 / 65535; + *p = stbi__get16be(s) >> 8 } else { for (i = 0; i < pixelCount; i++, p += 4) *p = stbi__get8(s); @@ -6331,6 +6334,8 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.07 (2015-09-13) fix compiler warnings; animated GIF support; + limited 16-bit PSD support 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit From 0eb5da55a71a6f4cac56882764ebcdf0b2f6089d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 05:12:53 -0700 Subject: [PATCH 064/522] er, fix typo in the fix-rmitton checkin --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index f2c9e49..2a51403 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5209,7 +5209,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int // Read the data. if (bitdepth == 16) { for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get16be(s) >> 8 + *p = stbi__get16be(s) >> 8; } else { for (i = 0; i < pixelCount; i++, p += 4) *p = stbi__get8(s); From 28a29dd0f1ffd4a64719851cb37f1665b2f286d0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 05:15:09 -0700 Subject: [PATCH 065/522] credit for michaelangel007 patch --- stb_image.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3931b7b..ee69422 100644 --- a/stb_image.h +++ b/stb_image.h @@ -147,7 +147,7 @@ Latest revision history: 2.07 (2015-09-13) fix compiler warnings; animated GIF support close; - limited 16-bit PSD support + limited 16-bit PSD support; #ifdef unused functions 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit @@ -209,6 +209,7 @@ isn't, let Sean know. Joseph Thomson Phil Jordan Nathan Reed + Michaelangel007@github LICENSE @@ -6344,7 +6345,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: 2.07 (2015-09-13) fix compiler warnings; animated GIF support; - limited 16-bit PSD support + limited 16-bit PSD support; #ifdef unused functions 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit From 90dc93a1ccbf63df53d3136c6e1b6225840814cf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 05:41:21 -0700 Subject: [PATCH 066/522] fix bug where we couldn't rewind a file that reached EOF, which can happen with < 92-byte PIC,PNM,HDR,TGA --- stb_image.h | 34 ++++++++++++++++++++++++---------- tests/image_test.c | 3 +++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/stb_image.h b/stb_image.h index ee69422..b82de7b 100644 --- a/stb_image.h +++ b/stb_image.h @@ -146,8 +146,9 @@ Latest revision history: - 2.07 (2015-09-13) fix compiler warnings; animated GIF support close; - limited 16-bit PSD support; #ifdef unused functions + 2.07 (2015-09-13) partial animated GIF support + limited 16-bit PSD support + minor bugs, code cleanup, and compiler warnings 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit @@ -757,7 +758,7 @@ typedef struct stbi_uc buffer_start[128]; stbi_uc *img_buffer, *img_buffer_end; - stbi_uc *img_buffer_original; + stbi_uc *img_buffer_original, *img_buffer_original_end; } stbi__context; @@ -769,7 +770,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) s->io.read = NULL; s->read_from_callbacks = 0; s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; - s->img_buffer_end = (stbi_uc *) buffer+len; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; } // initialize a callback-based context @@ -781,6 +782,7 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void * s->read_from_callbacks = 1; s->img_buffer_original = s->buffer_start; stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; } #ifndef STBI_NO_STDIO @@ -822,6 +824,7 @@ static void stbi__rewind(stbi__context *s) // but we just rewind to the beginning of the initial buffer, because // we only use it after doing 'test', which only ever looks at at most 92 bytes s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; } #ifndef STBI_NO_JPEG @@ -6111,14 +6114,22 @@ static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) int act_comp=0,num_packets=0,chained; stbi__pic_packet packets[10]; - stbi__skip(s, 92); + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); *x = stbi__get16be(s); *y = stbi__get16be(s); - if (stbi__at_eof(s)) return 0; + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { - stbi__rewind( s ); - return 0; + stbi__rewind( s ); + return 0; } stbi__skip(s, 8); @@ -6344,8 +6355,11 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: - 2.07 (2015-09-13) fix compiler warnings; animated GIF support; - limited 16-bit PSD support; #ifdef unused functions + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bit PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit diff --git a/tests/image_test.c b/tests/image_test.c index 3cdd011..bb395bc 100644 --- a/tests/image_test.c +++ b/tests/image_test.c @@ -73,14 +73,17 @@ int main(int argc, char **argv) int i, n; for (i=1; i < argc; ++i) { + int res; unsigned char *data; printf("%s\n", argv[i]); + res = stbi_info(argv[1], &w, &h, &n); data = stbi_load(argv[i], &w, &h, &n, 4); if (data) free(data); else printf("Failed &n\n"); data = stbi_load(argv[i], &w, &h, 0, 1); if (data) free(data); else printf("Failed 1\n"); data = stbi_load(argv[i], &w, &h, 0, 2); if (data) free(data); else printf("Failed 2\n"); data = stbi_load(argv[i], &w, &h, 0, 3); if (data) free(data); else printf("Failed 3\n"); data = stbi_load(argv[i], &w, &h, 0, 4); assert(data); + assert(res); if (data) { char fname[512]; stb_splitpath(fname, argv[i], STB_FILE); From 33c9010223f34ad5f4f033d8bf0baf0cdccec60b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 05:51:16 -0700 Subject: [PATCH 067/522] update version & version history --- stb_easy_font.h | 7 ++++++- tests/test_c_compilation.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/stb_easy_font.h b/stb_easy_font.h index a7e4227..4dee383 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -1,4 +1,4 @@ -// stb_easy_font.h - v0.5 - bitmap font for 3D rendering - public domain +// stb_easy_font.h - v0.6 - bitmap font for 3D rendering - public domain // Sean Barrett, Feb 2015 // // Easy-to-deploy, @@ -74,6 +74,11 @@ // recognized, you are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. // +// VERSION HISTORY +// +// (2015-09-13) 0.6 #include ; updated license +// (2015-02-01) 0.5 First release + #if 0 void print_string(float x, float y, char *text, float r, float g, float b) { diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index 309be5a..de25330 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -8,7 +8,9 @@ #define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION #define STB_VOXEL_RENDER_IMPLEMENTATION +#define STB_EASY_FONT_IMPLEMENTATION +#include "stb_easy_font.h" #include "stb_herringbone_wang_tile.h" #include "stb_image.h" #include "stb_image_write.h" From 24602db4a540150dea93a6e6fdeeffa2ce8629bb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 05:53:56 -0700 Subject: [PATCH 068/522] credits for previous patch --- stb.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/stb.h b/stb.h index 5f989c1..cde4a0d 100644 --- a/stb.h +++ b/stb.h @@ -1,4 +1,4 @@ -/* stb.h - v2.24 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h +/* stb.h - v2.25 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h no warranty is offered or implied; use this code at your own risk This is a single header file with a bunch of useful utilities @@ -25,6 +25,7 @@ Version History + 2.25 various warning & bugfixes 2.24 various warning & bugfixes 2.23 fix 2.22 2.22 64-bit fixes from '!='; fix stb_sdict_copy() to have preferred name @@ -173,6 +174,13 @@ This software is in the public domain. Where that dedication is not recognized, you are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. +CREDITS + +Written by Sean Barrett. + +Fixes: + Philipp Wiesemann + */ #ifndef STB__INCLUDE_STB_H From 2adf6d29aa44bd3bc9d9116bd171ab76ebee4c40 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:00:06 -0700 Subject: [PATCH 069/522] credits --- stb.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb.h b/stb.h index 9f2861b..5094eb5 100644 --- a/stb.h +++ b/stb.h @@ -180,6 +180,8 @@ Written by Sean Barrett. Fixes: Philipp Wiesemann + Robert Nix + r-lyeh */ From 5583b62a70ca7d6740e152dddd343add7d8ec2ca Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:05:24 -0700 Subject: [PATCH 070/522] credits --- stb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb.h b/stb.h index 551ee6d..cd09459 100644 --- a/stb.h +++ b/stb.h @@ -182,6 +182,7 @@ Fixes: Philipp Wiesemann Robert Nix r-lyeh + blackpawn */ From 97dfb12f71e1308c669c55d8f5ffb1eb5ece3516 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:06:37 -0700 Subject: [PATCH 071/522] credits --- stb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb.h b/stb.h index e57541a..8b01456 100644 --- a/stb.h +++ b/stb.h @@ -183,6 +183,7 @@ Fixes: Robert Nix r-lyeh blackpawn + Mojofreem@github */ From f0268375da05b26fdba1cac61650997a0aaf5b1a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:16:52 -0700 Subject: [PATCH 072/522] credit --- stb.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/stb.h b/stb.h index bed586c..d8aaf37 100644 --- a/stb.h +++ b/stb.h @@ -176,15 +176,16 @@ distribute, and modify this file as you see fit. CREDITS -Written by Sean Barrett. + Written by Sean Barrett. -Fixes: - Philipp Wiesemann - Robert Nix - r-lyeh - blackpawn - Mojofreem@github - Ryan Whitworth + Fixes: + Philipp Wiesemann + Robert Nix + r-lyeh + blackpawn + Mojofreem@github + Ryan Whitworth + Vincent Isambart */ #ifndef STB__INCLUDE_STB_H From 5863a4efe1a6022403d9f65f1ef4204082853237 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:28:46 -0700 Subject: [PATCH 073/522] delete stb_vorbis.h which leaked in from somebody's pull request --- stb_vorbis.h | 5463 -------------------------------------------------- 1 file changed, 5463 deletions(-) delete mode 100644 stb_vorbis.h diff --git a/stb_vorbis.h b/stb_vorbis.h deleted file mode 100644 index e71f0b8..0000000 --- a/stb_vorbis.h +++ /dev/null @@ -1,5463 +0,0 @@ -// Ogg Vorbis audio decoder - v1.05 - public domain -// http://nothings.org/stb_vorbis/ -// -// Written by Sean Barrett in 2007, last updated in 2014 -// Sponsored by RAD Game Tools. -// -// Placed in the public domain April 2007 by the author: no copyright -// is claimed, and you may use it for any purpose you like. -// -// No warranty for any purpose is expressed or implied by the author (nor -// by RAD Game Tools). Report bugs and send enhancements to the author. -// -// Limitations: -// -// - seeking not supported except manually via PUSHDATA api -// - floor 0 not supported (used in old ogg vorbis files pre-2004) -// - lossless sample-truncation at beginning ignored -// - cannot concatenate multiple vorbis streams -// - sample positions are 32-bit, limiting seekable 192Khz -// files to around 6 hours (Ogg supports 64-bit) -// -// Bugfix/warning contributors: -// Terje Mathisen Niklas Frykholm Andy Hill -// Casey Muratori John Bolton Gargaj -// Laurent Gomila Marc LeBlanc Ronny Chevalier -// Bernhard Wodo Evan Balster "alxprd"@github -// Tom Beaumont Ingo Leitgeb Nicolas Guillemot -// (If you reported a bug but do not appear in this list, it is because -// someone else reported the bug before you. There were too many of you to -// list them all because I was lax about updating for a long time, sorry.) -// -// Partial history: -// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant -// 1.04 - 2014/08/27 - fix missing const-correct case in API -// 1.03 - 2014/08/07 - warning fixes -// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows -// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct) -// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel; -// (API change) report sample rate for decode-full-file funcs -// 0.99996 - - bracket #include for macintosh compilation -// 0.99995 - - avoid alias-optimization issue in float-to-int conversion -// -// See end of file for full version history. - - -////////////////////////////////////////////////////////////////////////////// -// -// HEADER BEGINS HERE -// - -#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H -#define STB_VORBIS_INCLUDE_STB_VORBIS_H - -#ifdef _WIN32 - #define _CRT_SECURE_NO_WARNINGS -#endif - -#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) -#define STB_VORBIS_NO_STDIO 1 -#endif - -#ifndef STB_VORBIS_NO_STDIO -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/////////// THREAD SAFETY - -// Individual stb_vorbis* handles are not thread-safe; you cannot decode from -// them from multiple threads at the same time. However, you can have multiple -// stb_vorbis* handles and decode from them independently in multiple thrads. - - -/////////// MEMORY ALLOCATION - -// normally stb_vorbis uses malloc() to allocate memory at startup, -// and alloca() to allocate temporary memory during a frame on the -// stack. (Memory consumption will depend on the amount of setup -// data in the file and how you set the compile flags for speed -// vs. size. In my test files the maximal-size usage is ~150KB.) -// -// You can modify the wrapper functions in the source (setup_malloc, -// setup_temp_malloc, temp_malloc) to change this behavior, or you -// can use a simpler allocation model: you pass in a buffer from -// which stb_vorbis will allocate _all_ its memory (including the -// temp memory). "open" may fail with a VORBIS_outofmem if you -// do not pass in enough data; there is no way to determine how -// much you do need except to succeed (at which point you can -// query get_info to find the exact amount required. yes I know -// this is lame). -// -// If you pass in a non-NULL buffer of the type below, allocation -// will occur from it as described above. Otherwise just pass NULL -// to use malloc()/alloca() - -typedef struct -{ - char *alloc_buffer; - int alloc_buffer_length_in_bytes; -} stb_vorbis_alloc; - - -/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES - -typedef struct stb_vorbis stb_vorbis; - -typedef struct -{ - unsigned int sample_rate; - int channels; - - unsigned int setup_memory_required; - unsigned int setup_temp_memory_required; - unsigned int temp_memory_required; - - int max_frame_size; -} stb_vorbis_info; - -// get general information about the file -extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f); - -// get the last error detected (clears it, too) -extern int stb_vorbis_get_error(stb_vorbis *f); - -// close an ogg vorbis file and free all memory in use -extern void stb_vorbis_close(stb_vorbis *f); - -// this function returns the offset (in samples) from the beginning of the -// file that will be returned by the next decode, if it is known, or -1 -// otherwise. after a flush_pushdata() call, this may take a while before -// it becomes valid again. -// NOT WORKING YET after a seek with PULLDATA API -extern int stb_vorbis_get_sample_offset(stb_vorbis *f); - -// returns the current seek point within the file, or offset from the beginning -// of the memory buffer. In pushdata mode it returns 0. -extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); - -/////////// PUSHDATA API - -#ifndef STB_VORBIS_NO_PUSHDATA_API - -// this API allows you to get blocks of data from any source and hand -// them to stb_vorbis. you have to buffer them; stb_vorbis will tell -// you how much it used, and you have to give it the rest next time; -// and stb_vorbis may not have enough data to work with and you will -// need to give it the same data again PLUS more. Note that the Vorbis -// specification does not bound the size of an individual frame. - -extern stb_vorbis *stb_vorbis_open_pushdata( - unsigned char *datablock, int datablock_length_in_bytes, - int *datablock_memory_consumed_in_bytes, - int *error, - stb_vorbis_alloc *alloc_buffer); -// create a vorbis decoder by passing in the initial data block containing -// the ogg&vorbis headers (you don't need to do parse them, just provide -// the first N bytes of the file--you're told if it's not enough, see below) -// on success, returns an stb_vorbis *, does not set error, returns the amount of -// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; -// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed -// if returns NULL and *error is VORBIS_need_more_data, then the input block was -// incomplete and you need to pass in a larger block from the start of the file - -extern int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes, - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples - ); -// decode a frame of audio sample data if possible from the passed-in data block -// -// return value: number of bytes we used from datablock -// -// possible cases: -// 0 bytes used, 0 samples output (need more data) -// N bytes used, 0 samples output (resynching the stream, keep going) -// N bytes used, M samples output (one frame of data) -// note that after opening a file, you will ALWAYS get one N-bytes,0-sample -// frame, because Vorbis always "discards" the first frame. -// -// Note that on resynch, stb_vorbis will rarely consume all of the buffer, -// instead only datablock_length_in_bytes-3 or less. This is because it wants -// to avoid missing parts of a page header if they cross a datablock boundary, -// without writing state-machiney code to record a partial detection. -// -// The number of channels returned are stored in *channels (which can be -// NULL--it is always the same as the number of channels reported by -// get_info). *output will contain an array of float* buffers, one per -// channel. In other words, (*output)[0][0] contains the first sample from -// the first channel, and (*output)[1][0] contains the first sample from -// the second channel. - -extern void stb_vorbis_flush_pushdata(stb_vorbis *f); -// inform stb_vorbis that your next datablock will not be contiguous with -// previous ones (e.g. you've seeked in the data); future attempts to decode -// frames will cause stb_vorbis to resynchronize (as noted above), and -// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it -// will begin decoding the _next_ frame. -// -// if you want to seek using pushdata, you need to seek in your file, then -// call stb_vorbis_flush_pushdata(), then start calling decoding, then once -// decoding is returning you data, call stb_vorbis_get_sample_offset, and -// if you don't like the result, seek your file again and repeat. -#endif - - -////////// PULLING INPUT API - -#ifndef STB_VORBIS_NO_PULLDATA_API -// This API assumes stb_vorbis is allowed to pull data from a source-- -// either a block of memory containing the _entire_ vorbis stream, or a -// FILE * that you or it create, or possibly some other reading mechanism -// if you go modify the source to replace the FILE * case with some kind -// of callback to your code. (But if you don't support seeking, you may -// just want to go ahead and use pushdata.) - -#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION) -extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output); -#endif -#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION) -extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output); -#endif -// decode an entire file and output the data interleaved into a malloc()ed -// buffer stored in *output. The return value is the number of samples -// decoded, or -1 if the file could not be opened or was not an ogg vorbis file. -// When you're done with it, just free() the pointer returned in *output. - -extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, - int *error, stb_vorbis_alloc *alloc_buffer); -// create an ogg vorbis decoder from an ogg vorbis stream in memory (note -// this must be the entire stream!). on failure, returns NULL and sets *error - -#ifndef STB_VORBIS_NO_STDIO -extern stb_vorbis * stb_vorbis_open_filename(const char *filename, - int *error, stb_vorbis_alloc *alloc_buffer); -// create an ogg vorbis decoder from a filename via fopen(). on failure, -// returns NULL and sets *error (possibly to VORBIS_file_open_failure). - -extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, - int *error, stb_vorbis_alloc *alloc_buffer); -// create an ogg vorbis decoder from an open FILE *, looking for a stream at -// the _current_ seek point (ftell). on failure, returns NULL and sets *error. -// note that stb_vorbis must "own" this stream; if you seek it in between -// calls to stb_vorbis, it will become confused. Morever, if you attempt to -// perform stb_vorbis_seek_*() operations on this file, it will assume it -// owns the _entire_ rest of the file after the start point. Use the next -// function, stb_vorbis_open_file_section(), to limit it. - -extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, - int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len); -// create an ogg vorbis decoder from an open FILE *, looking for a stream at -// the _current_ seek point (ftell); the stream will be of length 'len' bytes. -// on failure, returns NULL and sets *error. note that stb_vorbis must "own" -// this stream; if you seek it in between calls to stb_vorbis, it will become -// confused. -#endif - -extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); -extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); -// NOT WORKING YET -// these functions seek in the Vorbis file to (approximately) 'sample_number'. -// after calling seek_frame(), the next call to get_frame_*() will include -// the specified sample. after calling stb_vorbis_seek(), the next call to -// stb_vorbis_get_samples_* will start with the specified sample. If you -// do not need to seek to EXACTLY the target sample when using get_samples_*, -// you can also use seek_frame(). - -extern void stb_vorbis_seek_start(stb_vorbis *f); -// this function is equivalent to stb_vorbis_seek(f,0), but it -// actually works - -extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); -extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); -// these functions return the total length of the vorbis stream - -extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output); -// decode the next frame and return the number of samples. the number of -// channels returned are stored in *channels (which can be NULL--it is always -// the same as the number of channels reported by get_info). *output will -// contain an array of float* buffers, one per channel. These outputs will -// be overwritten on the next call to stb_vorbis_get_frame_*. -// -// You generally should not intermix calls to stb_vorbis_get_frame_*() -// and stb_vorbis_get_samples_*(), since the latter calls the former. - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); -extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); -#endif -// decode the next frame and return the number of samples per channel. the -// data is coerced to the number of channels you request according to the -// channel coercion rules (see below). You must pass in the size of your -// buffer(s) so that stb_vorbis will not overwrite the end of the buffer. -// The maximum buffer size needed can be gotten from get_info(); however, -// the Vorbis I specification implies an absolute maximum of 4096 samples -// per channel. Note that for interleaved data, you pass in the number of -// shorts (the size of your array), but the return value is the number of -// samples per channel, not the total number of samples. - -// Channel coercion rules: -// Let M be the number of channels requested, and N the number of channels present, -// and Cn be the nth channel; let stereo L be the sum of all L and center channels, -// and stereo R be the sum of all R and center channels (channel assignment from the -// vorbis spec). -// M N output -// 1 k sum(Ck) for all k -// 2 * stereo L, stereo R -// k l k > l, the first l channels, then 0s -// k l k <= l, the first k channels -// Note that this is not _good_ surround etc. mixing at all! It's just so -// you get something useful. - -extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats); -extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples); -// gets num_samples samples, not necessarily on a frame boundary--this requires -// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. -// Returns the number of samples stored per channel; it may be less than requested -// at the end of the file. If there are no more samples in the file, returns 0. - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts); -extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples); -#endif -// gets num_samples samples, not necessarily on a frame boundary--this requires -// buffering so you have to supply the buffers. Applies the coercion rules above -// to produce 'channels' channels. Returns the number of samples stored per channel; -// it may be less than requested at the end of the file. If there are no more -// samples in the file, returns 0. - -#endif - -//////// ERROR CODES - -enum STBVorbisError -{ - VORBIS__no_error, - - VORBIS_need_more_data=1, // not a real error - - VORBIS_invalid_api_mixing, // can't mix API modes - VORBIS_outofmem, // not enough memory - VORBIS_feature_not_supported, // uses floor 0 - VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small - VORBIS_file_open_failure, // fopen() failed - VORBIS_seek_without_length, // can't seek in unknown-length file - - VORBIS_unexpected_eof=10, // file is truncated? - VORBIS_seek_invalid, // seek past EOF - - // decoding errors (corrupt/invalid stream) -- you probably - // don't care about the exact details of these - - // vorbis errors: - VORBIS_invalid_setup=20, - VORBIS_invalid_stream, - - // ogg errors: - VORBIS_missing_capture_pattern=30, - VORBIS_invalid_stream_structure_version, - VORBIS_continued_packet_flag_invalid, - VORBIS_incorrect_stream_serial_number, - VORBIS_invalid_first_page, - VORBIS_bad_packet_type, - VORBIS_cant_find_last_page, - VORBIS_seek_failed, -}; - - -#ifdef __cplusplus -} -#endif - -#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H -// -// HEADER ENDS HERE -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef STB_VORBIS_HEADER_ONLY - -// global configuration settings (e.g. set these in the project/makefile), -// or just set them in this file at the top (although ideally the first few -// should be visible when the header file is compiled too, although it's not -// crucial) - -// STB_VORBIS_NO_PUSHDATA_API -// does not compile the code for the various stb_vorbis_*_pushdata() -// functions -// #define STB_VORBIS_NO_PUSHDATA_API - -// STB_VORBIS_NO_PULLDATA_API -// does not compile the code for the non-pushdata APIs -// #define STB_VORBIS_NO_PULLDATA_API - -// STB_VORBIS_NO_STDIO -// does not compile the code for the APIs that use FILE *s internally -// or externally (implied by STB_VORBIS_NO_PULLDATA_API) -// #define STB_VORBIS_NO_STDIO - -// STB_VORBIS_NO_INTEGER_CONVERSION -// does not compile the code for converting audio sample data from -// float to integer (implied by STB_VORBIS_NO_PULLDATA_API) -// #define STB_VORBIS_NO_INTEGER_CONVERSION - -// STB_VORBIS_NO_FAST_SCALED_FLOAT -// does not use a fast float-to-int trick to accelerate float-to-int on -// most platforms which requires endianness be defined correctly. -//#define STB_VORBIS_NO_FAST_SCALED_FLOAT - - -// STB_VORBIS_MAX_CHANNELS [number] -// globally define this to the maximum number of channels you need. -// The spec does not put a restriction on channels except that -// the count is stored in a byte, so 255 is the hard limit. -// Reducing this saves about 16 bytes per value, so using 16 saves -// (255-16)*16 or around 4KB. Plus anything other memory usage -// I forgot to account for. Can probably go as low as 8 (7.1 audio), -// 6 (5.1 audio), or 2 (stereo only). -#ifndef STB_VORBIS_MAX_CHANNELS -#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone? -#endif - -// STB_VORBIS_PUSHDATA_CRC_COUNT [number] -// after a flush_pushdata(), stb_vorbis begins scanning for the -// next valid page, without backtracking. when it finds something -// that looks like a page, it streams through it and verifies its -// CRC32. Should that validation fail, it keeps scanning. But it's -// possible that _while_ streaming through to check the CRC32 of -// one candidate page, it sees another candidate page. This #define -// determines how many "overlapping" candidate pages it can search -// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas -// garbage pages could be as big as 64KB, but probably average ~16KB. -// So don't hose ourselves by scanning an apparent 64KB page and -// missing a ton of real ones in the interim; so minimum of 2 -#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT -#define STB_VORBIS_PUSHDATA_CRC_COUNT 4 -#endif - -// STB_VORBIS_FAST_HUFFMAN_LENGTH [number] -// sets the log size of the huffman-acceleration table. Maximum -// supported value is 24. with larger numbers, more decodings are O(1), -// but the table size is larger so worse cache missing, so you'll have -// to probe (and try multiple ogg vorbis files) to find the sweet spot. -#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH -#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10 -#endif - -// STB_VORBIS_FAST_BINARY_LENGTH [number] -// sets the log size of the binary-search acceleration table. this -// is used in similar fashion to the fast-huffman size to set initial -// parameters for the binary search - -// STB_VORBIS_FAST_HUFFMAN_INT -// The fast huffman tables are much more efficient if they can be -// stored as 16-bit results instead of 32-bit results. This restricts -// the codebooks to having only 65535 possible outcomes, though. -// (At least, accelerated by the huffman table.) -#ifndef STB_VORBIS_FAST_HUFFMAN_INT -#define STB_VORBIS_FAST_HUFFMAN_SHORT -#endif - -// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH -// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls -// back on binary searching for the correct one. This requires storing -// extra tables with the huffman codes in sorted order. Defining this -// symbol trades off space for speed by forcing a linear search in the -// non-fast case, except for "sparse" codebooks. -// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH - -// STB_VORBIS_DIVIDES_IN_RESIDUE -// stb_vorbis precomputes the result of the scalar residue decoding -// that would otherwise require a divide per chunk. you can trade off -// space for time by defining this symbol. -// #define STB_VORBIS_DIVIDES_IN_RESIDUE - -// STB_VORBIS_DIVIDES_IN_CODEBOOK -// vorbis VQ codebooks can be encoded two ways: with every case explicitly -// stored, or with all elements being chosen from a small range of values, -// and all values possible in all elements. By default, stb_vorbis expands -// this latter kind out to look like the former kind for ease of decoding, -// because otherwise an integer divide-per-vector-element is required to -// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can -// trade off storage for speed. -//#define STB_VORBIS_DIVIDES_IN_CODEBOOK - -// STB_VORBIS_CODEBOOK_SHORTS -// The vorbis file format encodes VQ codebook floats as ax+b where a and -// b are floating point per-codebook constants, and x is a 16-bit int. -// Normally, stb_vorbis decodes them to floats rather than leaving them -// as 16-bit ints and computing ax+b while decoding. This is a speed/space -// tradeoff; you can save space by defining this flag. -#ifndef STB_VORBIS_CODEBOOK_SHORTS -#define STB_VORBIS_CODEBOOK_FLOATS -#endif - -// STB_VORBIS_DIVIDE_TABLE -// this replaces small integer divides in the floor decode loop with -// table lookups. made less than 1% difference, so disabled by default. - -// STB_VORBIS_NO_INLINE_DECODE -// disables the inlining of the scalar codebook fast-huffman decode. -// might save a little codespace; useful for debugging -// #define STB_VORBIS_NO_INLINE_DECODE - -// STB_VORBIS_NO_DEFER_FLOOR -// Normally we only decode the floor without synthesizing the actual -// full curve. We can instead synthesize the curve immediately. This -// requires more memory and is very likely slower, so I don't think -// you'd ever want to do it except for debugging. -// #define STB_VORBIS_NO_DEFER_FLOOR - - - - -////////////////////////////////////////////////////////////////////////////// - -#ifdef STB_VORBIS_NO_PULLDATA_API - #define STB_VORBIS_NO_INTEGER_CONVERSION - #define STB_VORBIS_NO_STDIO -#endif - -#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) - #define STB_VORBIS_NO_STDIO 1 -#endif - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT - - // only need endianness for fast-float-to-int, which we don't - // use for pushdata - - #ifndef STB_VORBIS_BIG_ENDIAN - #define STB_VORBIS_ENDIAN 0 - #else - #define STB_VORBIS_ENDIAN 1 - #endif - -#endif -#endif - - -#ifndef STB_VORBIS_NO_STDIO -#include -#endif - -#ifndef STB_VORBIS_NO_CRT -#include -#include -#include -#include -#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) -#include -#endif -#else -#define NULL 0 -#endif - -#if !defined(_MSC_VER) && !(defined(__MINGW32__) && defined(__forceinline)) - #if __GNUC__ - #define __forceinline inline - #else - #define __forceinline - #endif -#endif - -#if STB_VORBIS_MAX_CHANNELS > 256 -#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range" -#endif - -#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24 -#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range" -#endif - - -#define MAX_BLOCKSIZE_LOG 13 // from specification -#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) - - -typedef unsigned char uint8; -typedef signed char int8; -typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned int uint32; -typedef signed int int32; - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#ifdef STB_VORBIS_CODEBOOK_FLOATS -typedef float codetype; -#else -typedef uint16 codetype; -#endif - -// @NOTE -// -// Some arrays below are tagged "//varies", which means it's actually -// a variable-sized piece of data, but rather than malloc I assume it's -// small enough it's better to just allocate it all together with the -// main thing -// -// Most of the variables are specified with the smallest size I could pack -// them into. It might give better performance to make them all full-sized -// integers. It should be safe to freely rearrange the structures or change -// the sizes larger--nothing relies on silently truncating etc., nor the -// order of variables. - -#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH) -#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1) - -typedef struct -{ - int dimensions, entries; - uint8 *codeword_lengths; - float minimum_value; - float delta_value; - uint8 value_bits; - uint8 lookup_type; - uint8 sequence_p; - uint8 sparse; - uint32 lookup_values; - codetype *multiplicands; - uint32 *codewords; - #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT - int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; - #else - int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; - #endif - uint32 *sorted_codewords; - int *sorted_values; - int sorted_entries; -} Codebook; - -typedef struct -{ - uint8 order; - uint16 rate; - uint16 bark_map_size; - uint8 amplitude_bits; - uint8 amplitude_offset; - uint8 number_of_books; - uint8 book_list[16]; // varies -} Floor0; - -typedef struct -{ - uint8 partitions; - uint8 partition_class_list[32]; // varies - uint8 class_dimensions[16]; // varies - uint8 class_subclasses[16]; // varies - uint8 class_masterbooks[16]; // varies - int16 subclass_books[16][8]; // varies - uint16 Xlist[31*8+2]; // varies - uint8 sorted_order[31*8+2]; - uint8 neighbors[31*8+2][2]; - uint8 floor1_multiplier; - uint8 rangebits; - int values; -} Floor1; - -typedef union -{ - Floor0 floor0; - Floor1 floor1; -} Floor; - -typedef struct -{ - uint32 begin, end; - uint32 part_size; - uint8 classifications; - uint8 classbook; - uint8 **classdata; - int16 (*residue_books)[8]; -} Residue; - -typedef struct -{ - uint8 magnitude; - uint8 angle; - uint8 mux; -} MappingChannel; - -typedef struct -{ - uint16 coupling_steps; - MappingChannel *chan; - uint8 submaps; - uint8 submap_floor[15]; // varies - uint8 submap_residue[15]; // varies -} Mapping; - -typedef struct -{ - uint8 blockflag; - uint8 mapping; - uint16 windowtype; - uint16 transformtype; -} Mode; - -typedef struct -{ - uint32 goal_crc; // expected crc if match - int bytes_left; // bytes left in packet - uint32 crc_so_far; // running crc - int bytes_done; // bytes processed in _current_ chunk - uint32 sample_loc; // granule pos encoded in page -} CRCscan; - -typedef struct -{ - uint32 page_start, page_end; - uint32 after_previous_page_start; - uint32 first_decoded_sample; - uint32 last_decoded_sample; -} ProbedPage; - -struct stb_vorbis -{ - // user-accessible info - unsigned int sample_rate; - int channels; - - unsigned int setup_memory_required; - unsigned int temp_memory_required; - unsigned int setup_temp_memory_required; - - // input config -#ifndef STB_VORBIS_NO_STDIO - FILE *f; - uint32 f_start; - int close_on_free; -#endif - - uint8 *stream; - uint8 *stream_start; - uint8 *stream_end; - - uint32 stream_len; - - uint8 push_mode; - - uint32 first_audio_page_offset; - - ProbedPage p_first, p_last; - - // memory management - stb_vorbis_alloc alloc; - int setup_offset; - int temp_offset; - - // run-time results - int eof; - enum STBVorbisError error; - - // user-useful data - - // header info - int blocksize[2]; - int blocksize_0, blocksize_1; - int codebook_count; - Codebook *codebooks; - int floor_count; - uint16 floor_types[64]; // varies - Floor *floor_config; - int residue_count; - uint16 residue_types[64]; // varies - Residue *residue_config; - int mapping_count; - Mapping *mapping; - int mode_count; - Mode mode_config[64]; // varies - - uint32 total_samples; - - // decode buffer - float *channel_buffers[STB_VORBIS_MAX_CHANNELS]; - float *outputs [STB_VORBIS_MAX_CHANNELS]; - - float *previous_window[STB_VORBIS_MAX_CHANNELS]; - int previous_length; - - #ifndef STB_VORBIS_NO_DEFER_FLOOR - int16 *finalY[STB_VORBIS_MAX_CHANNELS]; - #else - float *floor_buffers[STB_VORBIS_MAX_CHANNELS]; - #endif - - uint32 current_loc; // sample location of next frame to decode - int current_loc_valid; - - // per-blocksize precomputed data - - // twiddle factors - float *A[2],*B[2],*C[2]; - float *window[2]; - uint16 *bit_reverse[2]; - - // current page/packet/segment streaming info - uint32 serial; // stream serial number for verification - int last_page; - int segment_count; - uint8 segments[255]; - uint8 page_flag; - uint8 bytes_in_seg; - uint8 first_decode; - int next_seg; - int last_seg; // flag that we're on the last segment - int last_seg_which; // what was the segment number of the last seg? - uint32 acc; - int valid_bits; - int packet_bytes; - int end_seg_with_known_loc; - uint32 known_loc_for_packet; - int discard_samples_deferred; - uint32 samples_output; - - // push mode scanning - int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching -#ifndef STB_VORBIS_NO_PUSHDATA_API - CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; -#endif - - // sample-access - int channel_buffer_start; - int channel_buffer_end; -}; - -extern int my_prof(int slot); -//#define stb_prof my_prof - -#ifndef stb_prof -#define stb_prof(x) ((void) 0) -#endif - -#if defined(STB_VORBIS_NO_PUSHDATA_API) - #define IS_PUSH_MODE(f) FALSE -#elif defined(STB_VORBIS_NO_PULLDATA_API) - #define IS_PUSH_MODE(f) TRUE -#else - #define IS_PUSH_MODE(f) ((f)->push_mode) -#endif - -typedef struct stb_vorbis vorb; - -static int error(vorb *f, enum STBVorbisError e) -{ - f->error = e; - if (!f->eof && e != VORBIS_need_more_data) { - f->error=e; // breakpoint for debugging - } - return 0; -} - - -// these functions are used for allocating temporary memory -// while decoding. if you can afford the stack space, use -// alloca(); otherwise, provide a temp buffer and it will -// allocate out of those. - -#define array_size_required(count,size) (count*(sizeof(void *)+(size))) - -#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) -#ifdef dealloca -#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size)) -#else -#define temp_free(f,p) 0 -#endif -#define temp_alloc_save(f) ((f)->temp_offset) -#define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) - -#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size) - -// given a sufficiently large block of memory, make an array of pointers to subblocks of it -static void *make_block_array(void *mem, int count, int size) -{ - int i; - void ** p = (void **) mem; - char *q = (char *) (p + count); - for (i=0; i < count; ++i) { - p[i] = q; - q += size; - } - return p; -} - -static void *setup_malloc(vorb *f, int sz) -{ - sz = (sz+3) & ~3; - f->setup_memory_required += sz; - if (f->alloc.alloc_buffer) { - void *p = (char *) f->alloc.alloc_buffer + f->setup_offset; - if (f->setup_offset + sz > f->temp_offset) return NULL; - f->setup_offset += sz; - return p; - } - return sz ? malloc(sz) : NULL; -} - -static void setup_free(vorb *f, void *p) -{ - if (f->alloc.alloc_buffer) return; // do nothing; setup mem is not a stack - free(p); -} - -static void *setup_temp_malloc(vorb *f, int sz) -{ - sz = (sz+3) & ~3; - if (f->alloc.alloc_buffer) { - if (f->temp_offset - sz < f->setup_offset) return NULL; - f->temp_offset -= sz; - return (char *) f->alloc.alloc_buffer + f->temp_offset; - } - return malloc(sz); -} - -static void setup_temp_free(vorb *f, void *p, int sz) -{ - if (f->alloc.alloc_buffer) { - f->temp_offset += (sz+3)&~3; - return; - } - free(p); -} - -#define CRC32_POLY 0x04c11db7 // from spec - -static uint32 crc_table[256]; -static void crc32_init(void) -{ - int i,j; - uint32 s; - for(i=0; i < 256; i++) { - for (s=i<<24, j=0; j < 8; ++j) - s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); - crc_table[i] = s; - } -} - -static __forceinline uint32 crc32_update(uint32 crc, uint8 byte) -{ - return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; -} - - -// used in setup, and for huffman that doesn't go fast path -static unsigned int bit_reverse(unsigned int n) -{ - n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); - n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); - n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); - n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); - return (n >> 16) | (n << 16); -} - -static float square(float x) -{ - return x*x; -} - -// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3 -// as required by the specification. fast(?) implementation from stb.h -// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup -static int ilog(int32 n) -{ - static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; - - // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) - if (n < (1 << 14)) - if (n < (1 << 4)) return 0 + log2_4[n ]; - else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; - else return 10 + log2_4[n >> 10]; - else if (n < (1 << 24)) - if (n < (1 << 19)) return 15 + log2_4[n >> 15]; - else return 20 + log2_4[n >> 20]; - else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; - else if (n < (1 << 31)) return 30 + log2_4[n >> 30]; - else return 0; // signed n returns 0 -} - -#ifndef M_PI - #define M_PI 3.14159265358979323846264f // from CRC -#endif - -// code length assigned to a value with no huffman encoding -#define NO_CODE 255 - -/////////////////////// LEAF SETUP FUNCTIONS ////////////////////////// -// -// these functions are only called at setup, and only a few times -// per file - -static float float32_unpack(uint32 x) -{ - // from the specification - uint32 mantissa = x & 0x1fffff; - uint32 sign = x & 0x80000000; - uint32 exp = (x & 0x7fe00000) >> 21; - double res = sign ? -(double)mantissa : (double)mantissa; - return (float) ldexp((float)res, exp-788); -} - - -// zlib & jpeg huffman tables assume that the output symbols -// can either be arbitrarily arranged, or have monotonically -// increasing frequencies--they rely on the lengths being sorted; -// this makes for a very simple generation algorithm. -// vorbis allows a huffman table with non-sorted lengths. This -// requires a more sophisticated construction, since symbols in -// order do not map to huffman codes "in order". -static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values) -{ - if (!c->sparse) { - c->codewords [symbol] = huff_code; - } else { - c->codewords [count] = huff_code; - c->codeword_lengths[count] = len; - values [count] = symbol; - } -} - -static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) -{ - int i,k,m=0; - uint32 available[32]; - - memset(available, 0, sizeof(available)); - // find the first entry - for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; - if (k == n) { assert(c->sorted_entries == 0); return TRUE; } - // add to the list - add_entry(c, 0, k, m++, len[k], values); - // add all available leaves - for (i=1; i <= len[k]; ++i) - available[i] = 1 << (32-i); - // note that the above code treats the first case specially, - // but it's really the same as the following code, so they - // could probably be combined (except the initial code is 0, - // and I use 0 in available[] to mean 'empty') - for (i=k+1; i < n; ++i) { - uint32 res; - int z = len[i], y; - if (z == NO_CODE) continue; - // find lowest available leaf (should always be earliest, - // which is what the specification calls for) - // note that this property, and the fact we can never have - // more than one free leaf at a given level, isn't totally - // trivial to prove, but it seems true and the assert never - // fires, so! - while (z > 0 && !available[z]) --z; - if (z == 0) { assert(0); return FALSE; } - res = available[z]; - available[z] = 0; - add_entry(c, bit_reverse(res), i, m++, len[i], values); - // propogate availability up the tree - if (z != len[i]) { - for (y=len[i]; y > z; --y) { - assert(available[y] == 0); - available[y] = res + (1 << (32-y)); - } - } - } - return TRUE; -} - -// accelerated huffman table allows fast O(1) match of all symbols -// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH -static void compute_accelerated_huffman(Codebook *c) -{ - int i, len; - for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) - c->fast_huffman[i] = -1; - - len = c->sparse ? c->sorted_entries : c->entries; - #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT - if (len > 32767) len = 32767; // largest possible value we can encode! - #endif - for (i=0; i < len; ++i) { - if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) { - uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; - // set table entries for all bit combinations in the higher bits - while (z < FAST_HUFFMAN_TABLE_SIZE) { - c->fast_huffman[z] = i; - z += 1 << c->codeword_lengths[i]; - } - } - } -} - -#ifdef _MSC_VER -#define STBV_CDECL __cdecl -#else -#define STBV_CDECL -#endif - -static int STBV_CDECL uint32_compare(const void *p, const void *q) -{ - uint32 x = * (uint32 *) p; - uint32 y = * (uint32 *) q; - return x < y ? -1 : x > y; -} - -static int include_in_sort(Codebook *c, uint8 len) -{ - if (c->sparse) { assert(len != NO_CODE); return TRUE; } - if (len == NO_CODE) return FALSE; - if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; - return FALSE; -} - -// if the fast table above doesn't work, we want to binary -// search them... need to reverse the bits -static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) -{ - int i, len; - // build a list of all the entries - // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. - // this is kind of a frivolous optimization--I don't see any performance improvement, - // but it's like 4 extra lines of code, so. - if (!c->sparse) { - int k = 0; - for (i=0; i < c->entries; ++i) - if (include_in_sort(c, lengths[i])) - c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); - assert(k == c->sorted_entries); - } else { - for (i=0; i < c->sorted_entries; ++i) - c->sorted_codewords[i] = bit_reverse(c->codewords[i]); - } - - qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); - c->sorted_codewords[c->sorted_entries] = 0xffffffff; - - len = c->sparse ? c->sorted_entries : c->entries; - // now we need to indicate how they correspond; we could either - // #1: sort a different data structure that says who they correspond to - // #2: for each sorted entry, search the original list to find who corresponds - // #3: for each original entry, find the sorted entry - // #1 requires extra storage, #2 is slow, #3 can use binary search! - for (i=0; i < len; ++i) { - int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; - if (include_in_sort(c,huff_len)) { - uint32 code = bit_reverse(c->codewords[i]); - int x=0, n=c->sorted_entries; - while (n > 1) { - // invariant: sc[x] <= code < sc[x+n] - int m = x + (n >> 1); - if (c->sorted_codewords[m] <= code) { - x = m; - n -= (n>>1); - } else { - n >>= 1; - } - } - assert(c->sorted_codewords[x] == code); - if (c->sparse) { - c->sorted_values[x] = values[i]; - c->codeword_lengths[x] = huff_len; - } else { - c->sorted_values[x] = i; - } - } - } -} - -// only run while parsing the header (3 times) -static int vorbis_validate(uint8 *data) -{ - static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' }; - return memcmp(data, vorbis, 6) == 0; -} - -// called from setup only, once per code book -// (formula implied by specification) -static int lookup1_values(int entries, int dim) -{ - int r = (int) floor(exp((float) log((float) entries) / dim)); - if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; - ++r; // floor() to avoid _ftol() when non-CRT - assert(pow((float) r+1, dim) > entries); - assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above - return r; -} - -// called twice per file -static void compute_twiddle_factors(int n, float *A, float *B, float *C) -{ - int n4 = n >> 2, n8 = n >> 3; - int k,k2; - - for (k=k2=0; k < n4; ++k,k2+=2) { - A[k2 ] = (float) cos(4*k*M_PI/n); - A[k2+1] = (float) -sin(4*k*M_PI/n); - B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f; - B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f; - } - for (k=k2=0; k < n8; ++k,k2+=2) { - C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); - C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); - } -} - -static void compute_window(int n, float *window) -{ - int n2 = n >> 1, i; - for (i=0; i < n2; ++i) - window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); -} - -static void compute_bitreverse(int n, uint16 *rev) -{ - int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - int i, n8 = n >> 3; - for (i=0; i < n8; ++i) - rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2; -} - -static int init_blocksize(vorb *f, int b, int n) -{ - int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; - f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2); - f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2); - f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4); - if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); - compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); - f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2); - if (!f->window[b]) return error(f, VORBIS_outofmem); - compute_window(n, f->window[b]); - f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8); - if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); - compute_bitreverse(n, f->bit_reverse[b]); - return TRUE; -} - -static void neighbors(uint16 *x, int n, int *plow, int *phigh) -{ - int low = -1; - int high = 65536; - int i; - for (i=0; i < n; ++i) { - if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; } - if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; } - } -} - -// this has been repurposed so y is now the original index instead of y -typedef struct -{ - uint16 x,y; -} Point; - -static int STBV_CDECL point_compare(const void *p, const void *q) -{ - Point *a = (Point *) p; - Point *b = (Point *) q; - return a->x < b->x ? -1 : a->x > b->x; -} - -// -/////////////////////// END LEAF SETUP FUNCTIONS ////////////////////////// - - -#if defined(STB_VORBIS_NO_STDIO) - #define USE_MEMORY(z) TRUE -#else - #define USE_MEMORY(z) ((z)->stream) -#endif - -static uint8 get8(vorb *z) -{ - if (USE_MEMORY(z)) { - if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; } - return *z->stream++; - } - - #ifndef STB_VORBIS_NO_STDIO - { - int c = fgetc(z->f); - if (c == EOF) { z->eof = TRUE; return 0; } - return c; - } - #endif -} - -static uint32 get32(vorb *f) -{ - uint32 x; - x = get8(f); - x += get8(f) << 8; - x += get8(f) << 16; - x += get8(f) << 24; - return x; -} - -static int getn(vorb *z, uint8 *data, int n) -{ - if (USE_MEMORY(z)) { - if (z->stream+n > z->stream_end) { z->eof = 1; return 0; } - memcpy(data, z->stream, n); - z->stream += n; - return 1; - } - - #ifndef STB_VORBIS_NO_STDIO - if (fread(data, n, 1, z->f) == 1) - return 1; - else { - z->eof = 1; - return 0; - } - #endif -} - -static void skip(vorb *z, int n) -{ - if (USE_MEMORY(z)) { - z->stream += n; - if (z->stream >= z->stream_end) z->eof = 1; - return; - } - #ifndef STB_VORBIS_NO_STDIO - { - long x = ftell(z->f); - fseek(z->f, x+n, SEEK_SET); - } - #endif -} - -static int set_file_offset(stb_vorbis *f, unsigned int loc) -{ - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (f->push_mode) return 0; - #endif - f->eof = 0; - if (USE_MEMORY(f)) { - if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { - f->stream = f->stream_end; - f->eof = 1; - return 0; - } else { - f->stream = f->stream_start + loc; - return 1; - } - } - #ifndef STB_VORBIS_NO_STDIO - if (loc + f->f_start < loc || loc >= 0x80000000) { - loc = 0x7fffffff; - f->eof = 1; - } else { - loc += f->f_start; - } - if (!fseek(f->f, loc, SEEK_SET)) - return 1; - f->eof = 1; - fseek(f->f, f->f_start, SEEK_END); - return 0; - #endif -} - - -static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 }; - -static int capture_pattern(vorb *f) -{ - if (0x4f != get8(f)) return FALSE; - if (0x67 != get8(f)) return FALSE; - if (0x67 != get8(f)) return FALSE; - if (0x53 != get8(f)) return FALSE; - return TRUE; -} - -#define PAGEFLAG_continued_packet 1 -#define PAGEFLAG_first_page 2 -#define PAGEFLAG_last_page 4 - -static int start_page_no_capturepattern(vorb *f) -{ - uint32 loc0,loc1,n; - // stream structure version - if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); - // header flag - f->page_flag = get8(f); - // absolute granule position - loc0 = get32(f); - loc1 = get32(f); - // @TODO: validate loc0,loc1 as valid positions? - // stream serial number -- vorbis doesn't interleave, so discard - get32(f); - //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); - // page sequence number - n = get32(f); - f->last_page = n; - // CRC32 - get32(f); - // page_segments - f->segment_count = get8(f); - if (!getn(f, f->segments, f->segment_count)) - return error(f, VORBIS_unexpected_eof); - // assume we _don't_ know any the sample position of any segments - f->end_seg_with_known_loc = -2; - if (loc0 != ~0U || loc1 != ~0U) { - int i; - // determine which packet is the last one that will complete - for (i=f->segment_count-1; i >= 0; --i) - if (f->segments[i] < 255) - break; - // 'i' is now the index of the _last_ segment of a packet that ends - if (i >= 0) { - f->end_seg_with_known_loc = i; - f->known_loc_for_packet = loc0; - } - } - if (f->first_decode) { - int i,len; - ProbedPage p; - len = 0; - for (i=0; i < f->segment_count; ++i) - len += f->segments[i]; - len += 27 + f->segment_count; - p.page_start = f->first_audio_page_offset; - p.page_end = p.page_start + len; - p.after_previous_page_start = p.page_start; - p.first_decoded_sample = 0; - p.last_decoded_sample = loc0; - f->p_first = p; - } - f->next_seg = 0; - return TRUE; -} - -static int start_page(vorb *f) -{ - if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); - return start_page_no_capturepattern(f); -} - -static int start_packet(vorb *f) -{ - while (f->next_seg == -1) { - if (!start_page(f)) return FALSE; - if (f->page_flag & PAGEFLAG_continued_packet) - return error(f, VORBIS_continued_packet_flag_invalid); - } - f->last_seg = FALSE; - f->valid_bits = 0; - f->packet_bytes = 0; - f->bytes_in_seg = 0; - // f->next_seg is now valid - return TRUE; -} - -static int maybe_start_packet(vorb *f) -{ - if (f->next_seg == -1) { - int x = get8(f); - if (f->eof) return FALSE; // EOF at page boundary is not an error! - if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern); - if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); - if (!start_page_no_capturepattern(f)) return FALSE; - if (f->page_flag & PAGEFLAG_continued_packet) { - // set up enough state that we can read this packet if we want, - // e.g. during recovery - f->last_seg = FALSE; - f->bytes_in_seg = 0; - return error(f, VORBIS_continued_packet_flag_invalid); - } - } - return start_packet(f); -} - -static int next_segment(vorb *f) -{ - int len; - if (f->last_seg) return 0; - if (f->next_seg == -1) { - f->last_seg_which = f->segment_count-1; // in case start_page fails - if (!start_page(f)) { f->last_seg = 1; return 0; } - if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); - } - len = f->segments[f->next_seg++]; - if (len < 255) { - f->last_seg = TRUE; - f->last_seg_which = f->next_seg-1; - } - if (f->next_seg >= f->segment_count) - f->next_seg = -1; - assert(f->bytes_in_seg == 0); - f->bytes_in_seg = len; - return len; -} - -#define EOP (-1) -#define INVALID_BITS (-1) - -static int get8_packet_raw(vorb *f) -{ - if (!f->bytes_in_seg) { // CLANG! - if (f->last_seg) return EOP; - else if (!next_segment(f)) return EOP; - } - assert(f->bytes_in_seg > 0); - --f->bytes_in_seg; - ++f->packet_bytes; - return get8(f); -} - -static int get8_packet(vorb *f) -{ - int x = get8_packet_raw(f); - f->valid_bits = 0; - return x; -} - -static void flush_packet(vorb *f) -{ - while (get8_packet_raw(f) != EOP); -} - -// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important -// as the huffman decoder? -static uint32 get_bits(vorb *f, int n) -{ - uint32 z; - - if (f->valid_bits < 0) return 0; - if (f->valid_bits < n) { - if (n > 24) { - // the accumulator technique below would not work correctly in this case - z = get_bits(f, 24); - z += get_bits(f, n-24) << 24; - return z; - } - if (f->valid_bits == 0) f->acc = 0; - while (f->valid_bits < n) { - int z = get8_packet_raw(f); - if (z == EOP) { - f->valid_bits = INVALID_BITS; - return 0; - } - f->acc += z << f->valid_bits; - f->valid_bits += 8; - } - } - if (f->valid_bits < 0) return 0; - z = f->acc & ((1 << n)-1); - f->acc >>= n; - f->valid_bits -= n; - return z; -} - -// @OPTIMIZE: primary accumulator for huffman -// expand the buffer to as many bits as possible without reading off end of packet -// it might be nice to allow f->valid_bits and f->acc to be stored in registers, -// e.g. cache them locally and decode locally -static __forceinline void prep_huffman(vorb *f) -{ - if (f->valid_bits <= 24) { - if (f->valid_bits == 0) f->acc = 0; - do { - int z; - if (f->last_seg && !f->bytes_in_seg) return; - z = get8_packet_raw(f); - if (z == EOP) return; - f->acc += z << f->valid_bits; - f->valid_bits += 8; - } while (f->valid_bits <= 24); - } -} - -enum -{ - VORBIS_packet_id = 1, - VORBIS_packet_comment = 3, - VORBIS_packet_setup = 5, -}; - -static int codebook_decode_scalar_raw(vorb *f, Codebook *c) -{ - int i; - prep_huffman(f); - - assert(c->sorted_codewords || c->codewords); - // cases to use binary search: sorted_codewords && !c->codewords - // sorted_codewords && c->entries > 8 - if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { - // binary search - uint32 code = bit_reverse(f->acc); - int x=0, n=c->sorted_entries, len; - - while (n > 1) { - // invariant: sc[x] <= code < sc[x+n] - int m = x + (n >> 1); - if (c->sorted_codewords[m] <= code) { - x = m; - n -= (n>>1); - } else { - n >>= 1; - } - } - // x is now the sorted index - if (!c->sparse) x = c->sorted_values[x]; - // x is now sorted index if sparse, or symbol otherwise - len = c->codeword_lengths[x]; - if (f->valid_bits >= len) { - f->acc >>= len; - f->valid_bits -= len; - return x; - } - - f->valid_bits = 0; - return -1; - } - - // if small, linear search - assert(!c->sparse); - for (i=0; i < c->entries; ++i) { - if (c->codeword_lengths[i] == NO_CODE) continue; - if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) { - if (f->valid_bits >= c->codeword_lengths[i]) { - f->acc >>= c->codeword_lengths[i]; - f->valid_bits -= c->codeword_lengths[i]; - return i; - } - f->valid_bits = 0; - return -1; - } - } - - error(f, VORBIS_invalid_stream); - f->valid_bits = 0; - return -1; -} - -#ifndef STB_VORBIS_NO_INLINE_DECODE - -#define DECODE_RAW(var, f,c) \ - if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) \ - prep_huffman(f); \ - var = f->acc & FAST_HUFFMAN_TABLE_MASK; \ - var = c->fast_huffman[var]; \ - if (var >= 0) { \ - int n = c->codeword_lengths[var]; \ - f->acc >>= n; \ - f->valid_bits -= n; \ - if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \ - } else { \ - var = codebook_decode_scalar_raw(f,c); \ - } - -#else - -static int codebook_decode_scalar(vorb *f, Codebook *c) -{ - int i; - if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) - prep_huffman(f); - // fast huffman table lookup - i = f->acc & FAST_HUFFMAN_TABLE_MASK; - i = c->fast_huffman[i]; - if (i >= 0) { - f->acc >>= c->codeword_lengths[i]; - f->valid_bits -= c->codeword_lengths[i]; - if (f->valid_bits < 0) { f->valid_bits = 0; return -1; } - return i; - } - return codebook_decode_scalar_raw(f,c); -} - -#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c); - -#endif - -#define DECODE(var,f,c) \ - DECODE_RAW(var,f,c) \ - if (c->sparse) var = c->sorted_values[var]; - -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) -#else - #define DECODE_VQ(var,f,c) DECODE(var,f,c) -#endif - - - - - - -// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case -// where we avoid one addition -#ifndef STB_VORBIS_CODEBOOK_FLOATS - #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value) - #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value) - #define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value) -#else - #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) - #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) - #define CODEBOOK_ELEMENT_BASE(c) (0) -#endif - -static int codebook_decode_start(vorb *f, Codebook *c) -{ - int z = -1; - - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) - error(f, VORBIS_invalid_stream); - else { - DECODE_VQ(z,f,c); - if (c->sparse) assert(z < c->sorted_entries); - if (z < 0) { // check for EOP - if (!f->bytes_in_seg) - if (f->last_seg) - return z; - error(f, VORBIS_invalid_stream); - } - } - return z; -} - -static int codebook_decode(vorb *f, Codebook *c, float *output, int len) -{ - int i,z = codebook_decode_start(f,c); - if (z < 0) return FALSE; - if (len > c->dimensions) len = c->dimensions; - -#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - float last = CODEBOOK_ELEMENT_BASE(c); - int div = 1; - for (i=0; i < len; ++i) { - int off = (z / div) % c->lookup_values; - float val = CODEBOOK_ELEMENT_FAST(c,off) + last; - output[i] += val; - if (c->sequence_p) last = val + c->minimum_value; - div *= c->lookup_values; - } - return TRUE; - } -#endif - - z *= c->dimensions; - if (c->sequence_p) { - float last = CODEBOOK_ELEMENT_BASE(c); - for (i=0; i < len; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - output[i] += val; - last = val + c->minimum_value; - } - } else { - float last = CODEBOOK_ELEMENT_BASE(c); - for (i=0; i < len; ++i) { - output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; - } - } - - return TRUE; -} - -static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step) -{ - int i,z = codebook_decode_start(f,c); - float last = CODEBOOK_ELEMENT_BASE(c); - if (z < 0) return FALSE; - if (len > c->dimensions) len = c->dimensions; - -#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - int div = 1; - for (i=0; i < len; ++i) { - int off = (z / div) % c->lookup_values; - float val = CODEBOOK_ELEMENT_FAST(c,off) + last; - output[i*step] += val; - if (c->sequence_p) last = val; - div *= c->lookup_values; - } - return TRUE; - } -#endif - - z *= c->dimensions; - for (i=0; i < len; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - output[i*step] += val; - if (c->sequence_p) last = val; - } - - return TRUE; -} - -static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode) -{ - int c_inter = *c_inter_p; - int p_inter = *p_inter_p; - int i,z, effective = c->dimensions; - - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); - - while (total_decode > 0) { - float last = CODEBOOK_ELEMENT_BASE(c); - DECODE_VQ(z,f,c); - #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - assert(!c->sparse || z < c->sorted_entries); - #endif - if (z < 0) { - if (!f->bytes_in_seg) - if (f->last_seg) return FALSE; - return error(f, VORBIS_invalid_stream); - } - - // if this will take us off the end of the buffers, stop short! - // we check by computing the length of the virtual interleaved - // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), - // and the length we'll be using (effective) - if (c_inter + p_inter*ch + effective > len * ch) { - effective = len*ch - (p_inter*ch - c_inter); - } - - #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - int div = 1; - for (i=0; i < effective; ++i) { - int off = (z / div) % c->lookup_values; - float val = CODEBOOK_ELEMENT_FAST(c,off) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - if (c->sequence_p) last = val; - div *= c->lookup_values; - } - } else - #endif - { - z *= c->dimensions; - if (c->sequence_p) { - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - last = val; - } - } else { - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == ch) { c_inter = 0; ++p_inter; } - } - } - } - - total_decode -= effective; - } - *c_inter_p = c_inter; - *p_inter_p = p_inter; - return TRUE; -} - -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK -static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **outputs, int *c_inter_p, int *p_inter_p, int len, int total_decode) -{ - int c_inter = *c_inter_p; - int p_inter = *p_inter_p; - int i,z, effective = c->dimensions; - - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); - - while (total_decode > 0) { - float last = CODEBOOK_ELEMENT_BASE(c); - DECODE_VQ(z,f,c); - - if (z < 0) { - if (!f->bytes_in_seg) - if (f->last_seg) return FALSE; - return error(f, VORBIS_invalid_stream); - } - - // if this will take us off the end of the buffers, stop short! - // we check by computing the length of the virtual interleaved - // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), - // and the length we'll be using (effective) - if (c_inter + p_inter*2 + effective > len * 2) { - effective = len*2 - (p_inter*2 - c_inter); - } - - { - z *= c->dimensions; - stb_prof(11); - if (c->sequence_p) { - // haven't optimized this case because I don't have any examples - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == 2) { c_inter = 0; ++p_inter; } - last = val; - } - } else { - i=0; - if (c_inter == 1) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - c_inter = 0; ++p_inter; - ++i; - } - { - float *z0 = outputs[0]; - float *z1 = outputs[1]; - for (; i+1 < effective;) { - float v0 = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - float v1 = CODEBOOK_ELEMENT_FAST(c,z+i+1) + last; - if (z0) - z0[p_inter] += v0; - if (z1) - z1[p_inter] += v1; - ++p_inter; - i += 2; - } - } - if (i < effective) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == 2) { c_inter = 0; ++p_inter; } - } - } - } - - total_decode -= effective; - } - *c_inter_p = c_inter; - *p_inter_p = p_inter; - return TRUE; -} -#endif - -static int predict_point(int x, int x0, int x1, int y0, int y1) -{ - int dy = y1 - y0; - int adx = x1 - x0; - // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? - int err = abs(dy) * (x - x0); - int off = err / adx; - return dy < 0 ? y0 - off : y0 + off; -} - -// the following table is block-copied from the specification -static float inverse_db_table[256] = -{ - 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, - 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, - 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, - 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, - 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, - 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, - 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, - 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, - 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, - 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, - 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, - 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, - 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, - 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, - 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, - 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, - 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, - 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, - 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, - 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, - 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, - 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, - 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, - 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, - 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, - 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, - 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, - 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, - 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, - 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, - 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, - 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, - 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, - 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, - 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, - 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, - 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, - 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, - 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, - 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, - 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, - 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, - 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, - 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, - 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, - 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, - 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, - 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, - 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, - 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, - 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, - 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, - 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, - 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, - 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, - 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, - 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, - 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, - 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, - 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, - 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, - 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, - 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, - 0.82788260f, 0.88168307f, 0.9389798f, 1.0f -}; - - -// @OPTIMIZE: if you want to replace this bresenham line-drawing routine, -// note that you must produce bit-identical output to decode correctly; -// this specific sequence of operations is specified in the spec (it's -// drawing integer-quantized frequency-space lines that the encoder -// expects to be exactly the same) -// ... also, isn't the whole point of Bresenham's algorithm to NOT -// have to divide in the setup? sigh. -#ifndef STB_VORBIS_NO_DEFER_FLOOR -#define LINE_OP(a,b) a *= b -#else -#define LINE_OP(a,b) a = b -#endif - -#ifdef STB_VORBIS_DIVIDE_TABLE -#define DIVTAB_NUMER 32 -#define DIVTAB_DENOM 64 -int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB -#endif - -static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n) -{ - int dy = y1 - y0; - int adx = x1 - x0; - int ady = abs(dy); - int base; - int x=x0,y=y0; - int err = 0; - int sy; - -#ifdef STB_VORBIS_DIVIDE_TABLE - if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) { - if (dy < 0) { - base = -integer_divide_table[ady][adx]; - sy = base-1; - } else { - base = integer_divide_table[ady][adx]; - sy = base+1; - } - } else { - base = dy / adx; - if (dy < 0) - sy = base - 1; - else - sy = base+1; - } -#else - base = dy / adx; - if (dy < 0) - sy = base - 1; - else - sy = base+1; -#endif - ady -= abs(base) * adx; - if (x1 > n) x1 = n; - LINE_OP(output[x], inverse_db_table[y]); - for (++x; x < x1; ++x) { - err += ady; - if (err >= adx) { - err -= adx; - y += sy; - } else - y += base; - LINE_OP(output[x], inverse_db_table[y]); - } -} - -static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype) -{ - int k; - if (rtype == 0) { - int step = n / book->dimensions; - for (k=0; k < step; ++k) - if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step)) - return FALSE; - } else { - for (k=0; k < n; ) { - if (!codebook_decode(f, book, target+offset, n-k)) - return FALSE; - k += book->dimensions; - offset += book->dimensions; - } - } - return TRUE; -} - -static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) -{ - int i,j,pass; - Residue *r = f->residue_config + rn; - int rtype = f->residue_types[rn]; - int c = r->classbook; - int classwords = f->codebooks[c].dimensions; - int n_read = r->end - r->begin; - int part_read = n_read / r->part_size; - int temp_alloc_point = temp_alloc_save(f); - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata)); - #else - int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); - #endif - - stb_prof(2); - for (i=0; i < ch; ++i) - if (!do_not_decode[i]) - memset(residue_buffers[i], 0, sizeof(float) * n); - - if (rtype == 2 && ch != 1) { - for (j=0; j < ch; ++j) - if (!do_not_decode[j]) - break; - if (j == ch) - goto done; - - stb_prof(3); - for (pass=0; pass < 8; ++pass) { - int pcount = 0, class_set = 0; - if (ch == 2) { - stb_prof(13); - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = (z & 1), p_inter = z>>1; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else - for (i=classwords-1; i >= 0; --i) { - classifications[0][i+pcount] = q % r->classifications; - q /= r->classifications; - } - #endif - } - stb_prof(5); - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else - int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - stb_prof(20); // accounts for X time - #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - #else - // saves 1% - if (!codebook_decode_deinterleave_repeat_2(f, book, residue_buffers, &c_inter, &p_inter, n, r->part_size)) - goto done; - #endif - stb_prof(7); - } else { - z += r->part_size; - c_inter = z & 1; - p_inter = z >> 1; - } - } - stb_prof(8); - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } else if (ch == 1) { - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = 0, p_inter = z; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else - for (i=classwords-1; i >= 0; --i) { - classifications[0][i+pcount] = q % r->classifications; - q /= r->classifications; - } - #endif - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else - int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - stb_prof(22); - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - stb_prof(3); - } else { - z += r->part_size; - c_inter = 0; - p_inter = z; - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } else { - while (pcount < part_read) { - int z = r->begin + pcount*r->part_size; - int c_inter = z % ch, p_inter = z/ch; - if (pass == 0) { - Codebook *c = f->codebooks+r->classbook; - int q; - DECODE(q,f,c); - if (q == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[0][class_set] = r->classdata[q]; - #else - for (i=classwords-1; i >= 0; --i) { - classifications[0][i+pcount] = q % r->classifications; - q /= r->classifications; - } - #endif - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - int z = r->begin + pcount*r->part_size; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[0][class_set][i]; - #else - int c = classifications[0][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - Codebook *book = f->codebooks + b; - stb_prof(22); - if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) - goto done; - stb_prof(3); - } else { - z += r->part_size; - c_inter = z % ch; - p_inter = z / ch; - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } - } - goto done; - } - stb_prof(9); - - for (pass=0; pass < 8; ++pass) { - int pcount = 0, class_set=0; - while (pcount < part_read) { - if (pass == 0) { - for (j=0; j < ch; ++j) { - if (!do_not_decode[j]) { - Codebook *c = f->codebooks+r->classbook; - int temp; - DECODE(temp,f,c); - if (temp == EOP) goto done; - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - part_classdata[j][class_set] = r->classdata[temp]; - #else - for (i=classwords-1; i >= 0; --i) { - classifications[j][i+pcount] = temp % r->classifications; - temp /= r->classifications; - } - #endif - } - } - } - for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { - for (j=0; j < ch; ++j) { - if (!do_not_decode[j]) { - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - int c = part_classdata[j][class_set][i]; - #else - int c = classifications[j][pcount]; - #endif - int b = r->residue_books[c][pass]; - if (b >= 0) { - float *target = residue_buffers[j]; - int offset = r->begin + pcount * r->part_size; - int n = r->part_size; - Codebook *book = f->codebooks + b; - if (!residue_decode(f, book, target, offset, n, rtype)) - goto done; - } - } - } - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - ++class_set; - #endif - } - } - done: - stb_prof(0); - temp_alloc_restore(f,temp_alloc_point); -} - - -#if 0 -// slow way for debugging -void inverse_mdct_slow(float *buffer, int n) -{ - int i,j; - int n2 = n >> 1; - float *x = (float *) malloc(sizeof(*x) * n2); - memcpy(x, buffer, sizeof(*x) * n2); - for (i=0; i < n; ++i) { - float acc = 0; - for (j=0; j < n2; ++j) - // formula from paper: - //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); - // formula from wikipedia - //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); - // these are equivalent, except the formula from the paper inverts the multiplier! - // however, what actually works is NO MULTIPLIER!?! - //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); - acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); - buffer[i] = acc; - } - free(x); -} -#elif 0 -// same as above, but just barely able to run in real time on modern machines -void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) -{ - float mcos[16384]; - int i,j; - int n2 = n >> 1, nmask = (n << 2) -1; - float *x = (float *) malloc(sizeof(*x) * n2); - memcpy(x, buffer, sizeof(*x) * n2); - for (i=0; i < 4*n; ++i) - mcos[i] = (float) cos(M_PI / 2 * i / n); - - for (i=0; i < n; ++i) { - float acc = 0; - for (j=0; j < n2; ++j) - acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask]; - buffer[i] = acc; - } - free(x); -} -#elif 0 -// transform to use a slow dct-iv; this is STILL basically trivial, -// but only requires half as many ops -void dct_iv_slow(float *buffer, int n) -{ - float mcos[16384]; - float x[2048]; - int i,j; - int n2 = n >> 1, nmask = (n << 3) - 1; - memcpy(x, buffer, sizeof(*x) * n); - for (i=0; i < 8*n; ++i) - mcos[i] = (float) cos(M_PI / 4 * i / n); - for (i=0; i < n; ++i) { - float acc = 0; - for (j=0; j < n; ++j) - acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask]; - buffer[i] = acc; - } -} - -void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) -{ - int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4; - float temp[4096]; - - memcpy(temp, buffer, n2 * sizeof(float)); - dct_iv_slow(temp, n2); // returns -c'-d, a-b' - - for (i=0; i < n4 ; ++i) buffer[i] = temp[i+n4]; // a-b' - for ( ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1]; // b-a', c+d' - for ( ; i < n ; ++i) buffer[i] = -temp[i - n3_4]; // c'+d -} -#endif - -#ifndef LIBVORBIS_MDCT -#define LIBVORBIS_MDCT 0 -#endif - -#if LIBVORBIS_MDCT -// directly call the vorbis MDCT using an interface documented -// by Jeff Roberts... useful for performance comparison -typedef struct -{ - int n; - int log2n; - - float *trig; - int *bitrev; - - float scale; -} mdct_lookup; - -extern void mdct_init(mdct_lookup *lookup, int n); -extern void mdct_clear(mdct_lookup *l); -extern void mdct_backward(mdct_lookup *init, float *in, float *out); - -mdct_lookup M1,M2; - -void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) -{ - mdct_lookup *M; - if (M1.n == n) M = &M1; - else if (M2.n == n) M = &M2; - else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } - else { - if (M2.n) __asm int 3; - mdct_init(&M2, n); - M = &M2; - } - - mdct_backward(M, buffer, buffer); -} -#endif - - -// the following were split out into separate functions while optimizing; -// they could be pushed back up but eh. __forceinline showed no change; -// they're probably already being inlined. -static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A) -{ - float *ee0 = e + i_off; - float *ee2 = ee0 + k_off; - int i; - - assert((n & 3) == 0); - for (i=(n>>2); i > 0; --i) { - float k00_20, k01_21; - k00_20 = ee0[ 0] - ee2[ 0]; - k01_21 = ee0[-1] - ee2[-1]; - ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0]; - ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1]; - ee2[ 0] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - - k00_20 = ee0[-2] - ee2[-2]; - k01_21 = ee0[-3] - ee2[-3]; - ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2]; - ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3]; - ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - - k00_20 = ee0[-4] - ee2[-4]; - k01_21 = ee0[-5] - ee2[-5]; - ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4]; - ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5]; - ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - - k00_20 = ee0[-6] - ee2[-6]; - k01_21 = ee0[-7] - ee2[-7]; - ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6]; - ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7]; - ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; - ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; - A += 8; - ee0 -= 8; - ee2 -= 8; - } -} - -static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1) -{ - int i; - float k00_20, k01_21; - - float *e0 = e + d0; - float *e2 = e0 + k_off; - - for (i=lim >> 2; i > 0; --i) { - k00_20 = e0[-0] - e2[-0]; - k01_21 = e0[-1] - e2[-1]; - e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0]; - e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1]; - e2[-0] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-1] = (k01_21)*A[0] + (k00_20) * A[1]; - - A += k1; - - k00_20 = e0[-2] - e2[-2]; - k01_21 = e0[-3] - e2[-3]; - e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2]; - e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3]; - e2[-2] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-3] = (k01_21)*A[0] + (k00_20) * A[1]; - - A += k1; - - k00_20 = e0[-4] - e2[-4]; - k01_21 = e0[-5] - e2[-5]; - e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4]; - e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5]; - e2[-4] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-5] = (k01_21)*A[0] + (k00_20) * A[1]; - - A += k1; - - k00_20 = e0[-6] - e2[-6]; - k01_21 = e0[-7] - e2[-7]; - e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6]; - e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7]; - e2[-6] = (k00_20)*A[0] - (k01_21) * A[1]; - e2[-7] = (k01_21)*A[0] + (k00_20) * A[1]; - - e0 -= 8; - e2 -= 8; - - A += k1; - } -} - -static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0) -{ - int i; - float A0 = A[0]; - float A1 = A[0+1]; - float A2 = A[0+a_off]; - float A3 = A[0+a_off+1]; - float A4 = A[0+a_off*2+0]; - float A5 = A[0+a_off*2+1]; - float A6 = A[0+a_off*3+0]; - float A7 = A[0+a_off*3+1]; - - float k00,k11; - - float *ee0 = e +i_off; - float *ee2 = ee0+k_off; - - for (i=n; i > 0; --i) { - k00 = ee0[ 0] - ee2[ 0]; - k11 = ee0[-1] - ee2[-1]; - ee0[ 0] = ee0[ 0] + ee2[ 0]; - ee0[-1] = ee0[-1] + ee2[-1]; - ee2[ 0] = (k00) * A0 - (k11) * A1; - ee2[-1] = (k11) * A0 + (k00) * A1; - - k00 = ee0[-2] - ee2[-2]; - k11 = ee0[-3] - ee2[-3]; - ee0[-2] = ee0[-2] + ee2[-2]; - ee0[-3] = ee0[-3] + ee2[-3]; - ee2[-2] = (k00) * A2 - (k11) * A3; - ee2[-3] = (k11) * A2 + (k00) * A3; - - k00 = ee0[-4] - ee2[-4]; - k11 = ee0[-5] - ee2[-5]; - ee0[-4] = ee0[-4] + ee2[-4]; - ee0[-5] = ee0[-5] + ee2[-5]; - ee2[-4] = (k00) * A4 - (k11) * A5; - ee2[-5] = (k11) * A4 + (k00) * A5; - - k00 = ee0[-6] - ee2[-6]; - k11 = ee0[-7] - ee2[-7]; - ee0[-6] = ee0[-6] + ee2[-6]; - ee0[-7] = ee0[-7] + ee2[-7]; - ee2[-6] = (k00) * A6 - (k11) * A7; - ee2[-7] = (k11) * A6 + (k00) * A7; - - ee0 -= k0; - ee2 -= k0; - } -} - -static __forceinline void iter_54(float *z) -{ - float k00,k11,k22,k33; - float y0,y1,y2,y3; - - k00 = z[ 0] - z[-4]; - y0 = z[ 0] + z[-4]; - y2 = z[-2] + z[-6]; - k22 = z[-2] - z[-6]; - - z[-0] = y0 + y2; // z0 + z4 + z2 + z6 - z[-2] = y0 - y2; // z0 + z4 - z2 - z6 - - // done with y0,y2 - - k33 = z[-3] - z[-7]; - - z[-4] = k00 + k33; // z0 - z4 + z3 - z7 - z[-6] = k00 - k33; // z0 - z4 - z3 + z7 - - // done with k33 - - k11 = z[-1] - z[-5]; - y1 = z[-1] + z[-5]; - y3 = z[-3] + z[-7]; - - z[-1] = y1 + y3; // z1 + z5 + z3 + z7 - z[-3] = y1 - y3; // z1 + z5 - z3 - z7 - z[-5] = k11 - k22; // z1 - z5 + z2 - z6 - z[-7] = k11 + k22; // z1 - z5 - z2 + z6 -} - -static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) -{ - int a_off = base_n >> 3; - float A2 = A[0+a_off]; - float *z = e + i_off; - float *base = z - 16 * n; - - while (z > base) { - float k00,k11; - - k00 = z[-0] - z[-8]; - k11 = z[-1] - z[-9]; - z[-0] = z[-0] + z[-8]; - z[-1] = z[-1] + z[-9]; - z[-8] = k00; - z[-9] = k11 ; - - k00 = z[ -2] - z[-10]; - k11 = z[ -3] - z[-11]; - z[ -2] = z[ -2] + z[-10]; - z[ -3] = z[ -3] + z[-11]; - z[-10] = (k00+k11) * A2; - z[-11] = (k11-k00) * A2; - - k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation - k11 = z[ -5] - z[-13]; - z[ -4] = z[ -4] + z[-12]; - z[ -5] = z[ -5] + z[-13]; - z[-12] = k11; - z[-13] = k00; - - k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation - k11 = z[ -7] - z[-15]; - z[ -6] = z[ -6] + z[-14]; - z[ -7] = z[ -7] + z[-15]; - z[-14] = (k00+k11) * A2; - z[-15] = (k00-k11) * A2; - - iter_54(z); - iter_54(z-8); - z -= 16; - } -} - -static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) -{ - int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; - int ld; - // @OPTIMIZE: reduce register pressure by using fewer variables? - int save_point = temp_alloc_save(f); - float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2)); - float *u=NULL,*v=NULL; - // twiddle factors - float *A = f->A[blocktype]; - - // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" - // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. - - // kernel from paper - - - // merged: - // copy and reflect spectral data - // step 0 - - // note that it turns out that the items added together during - // this step are, in fact, being added to themselves (as reflected - // by step 0). inexplicable inefficiency! this became obvious - // once I combined the passes. - - // so there's a missing 'times 2' here (for adding X to itself). - // this propogates through linearly to the end, where the numbers - // are 1/2 too small, and need to be compensated for. - - { - float *d,*e, *AA, *e_stop; - d = &buf2[n2-2]; - AA = A; - e = &buffer[0]; - e_stop = &buffer[n2]; - while (e != e_stop) { - d[1] = (e[0] * AA[0] - e[2]*AA[1]); - d[0] = (e[0] * AA[1] + e[2]*AA[0]); - d -= 2; - AA += 2; - e += 4; - } - - e = &buffer[n2-3]; - while (d >= buf2) { - d[1] = (-e[2] * AA[0] - -e[0]*AA[1]); - d[0] = (-e[2] * AA[1] + -e[0]*AA[0]); - d -= 2; - AA += 2; - e -= 4; - } - } - - // now we use symbolic names for these, so that we can - // possibly swap their meaning as we change which operations - // are in place - - u = buffer; - v = buf2; - - // step 2 (paper output is w, now u) - // this could be in place, but the data ends up in the wrong - // place... _somebody_'s got to swap it, so this is nominated - { - float *AA = &A[n2-8]; - float *d0,*d1, *e0, *e1; - - e0 = &v[n4]; - e1 = &v[0]; - - d0 = &u[n4]; - d1 = &u[0]; - - while (AA >= A) { - float v40_20, v41_21; - - v41_21 = e0[1] - e1[1]; - v40_20 = e0[0] - e1[0]; - d0[1] = e0[1] + e1[1]; - d0[0] = e0[0] + e1[0]; - d1[1] = v41_21*AA[4] - v40_20*AA[5]; - d1[0] = v40_20*AA[4] + v41_21*AA[5]; - - v41_21 = e0[3] - e1[3]; - v40_20 = e0[2] - e1[2]; - d0[3] = e0[3] + e1[3]; - d0[2] = e0[2] + e1[2]; - d1[3] = v41_21*AA[0] - v40_20*AA[1]; - d1[2] = v40_20*AA[0] + v41_21*AA[1]; - - AA -= 8; - - d0 += 4; - d1 += 4; - e0 += 4; - e1 += 4; - } - } - - // step 3 - ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - - // optimized step 3: - - // the original step3 loop can be nested r inside s or s inside r; - // it's written originally as s inside r, but this is dumb when r - // iterates many times, and s few. So I have two copies of it and - // switch between them halfway. - - // this is iteration 0 of step 3 - imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A); - imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A); - - // this is iteration 1 of step 3 - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16); - imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16); - - l=2; - for (; l < (ld-3)>>1; ++l) { - int k0 = n >> (l+2), k0_2 = k0>>1; - int lim = 1 << (l+1); - int i; - for (i=0; i < lim; ++i) - imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3)); - } - - for (; l < ld-6; ++l) { - int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1; - int rlim = n >> (l+6), r; - int lim = 1 << (l+1); - int i_off; - float *A0 = A; - i_off = n2-1; - for (r=rlim; r > 0; --r) { - imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); - A0 += k1*4; - i_off -= 8; - } - } - - // iterations with count: - // ld-6,-5,-4 all interleaved together - // the big win comes from getting rid of needless flops - // due to the constants on pass 5 & 4 being all 1 and 0; - // combining them to be simultaneous to improve cache made little difference - imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n); - - // output is u - - // step 4, 5, and 6 - // cannot be in-place because of step 5 - { - uint16 *bitrev = f->bit_reverse[blocktype]; - // weirdly, I'd have thought reading sequentially and writing - // erratically would have been better than vice-versa, but in - // fact that's not what my testing showed. (That is, with - // j = bitreverse(i), do you read i and write j, or read j and write i.) - - float *d0 = &v[n4-4]; - float *d1 = &v[n2-4]; - while (d0 >= v) { - int k4; - - k4 = bitrev[0]; - d1[3] = u[k4+0]; - d1[2] = u[k4+1]; - d0[3] = u[k4+2]; - d0[2] = u[k4+3]; - - k4 = bitrev[1]; - d1[1] = u[k4+0]; - d1[0] = u[k4+1]; - d0[1] = u[k4+2]; - d0[0] = u[k4+3]; - - d0 -= 4; - d1 -= 4; - bitrev += 2; - } - } - // (paper output is u, now v) - - - // data must be in buf2 - assert(v == buf2); - - // step 7 (paper output is v, now v) - // this is now in place - { - float *C = f->C[blocktype]; - float *d, *e; - - d = v; - e = v + n2 - 4; - - while (d < e) { - float a02,a11,b0,b1,b2,b3; - - a02 = d[0] - e[2]; - a11 = d[1] + e[3]; - - b0 = C[1]*a02 + C[0]*a11; - b1 = C[1]*a11 - C[0]*a02; - - b2 = d[0] + e[ 2]; - b3 = d[1] - e[ 3]; - - d[0] = b2 + b0; - d[1] = b3 + b1; - e[2] = b2 - b0; - e[3] = b1 - b3; - - a02 = d[2] - e[0]; - a11 = d[3] + e[1]; - - b0 = C[3]*a02 + C[2]*a11; - b1 = C[3]*a11 - C[2]*a02; - - b2 = d[2] + e[ 0]; - b3 = d[3] - e[ 1]; - - d[2] = b2 + b0; - d[3] = b3 + b1; - e[0] = b2 - b0; - e[1] = b1 - b3; - - C += 4; - d += 4; - e -= 4; - } - } - - // data must be in buf2 - - - // step 8+decode (paper output is X, now buffer) - // this generates pairs of data a la 8 and pushes them directly through - // the decode kernel (pushing rather than pulling) to avoid having - // to make another pass later - - // this cannot POSSIBLY be in place, so we refer to the buffers directly - - { - float *d0,*d1,*d2,*d3; - - float *B = f->B[blocktype] + n2 - 8; - float *e = buf2 + n2 - 8; - d0 = &buffer[0]; - d1 = &buffer[n2-4]; - d2 = &buffer[n2]; - d3 = &buffer[n-4]; - while (e >= v) { - float p0,p1,p2,p3; - - p3 = e[6]*B[7] - e[7]*B[6]; - p2 = -e[6]*B[6] - e[7]*B[7]; - - d0[0] = p3; - d1[3] = - p3; - d2[0] = p2; - d3[3] = p2; - - p1 = e[4]*B[5] - e[5]*B[4]; - p0 = -e[4]*B[4] - e[5]*B[5]; - - d0[1] = p1; - d1[2] = - p1; - d2[1] = p0; - d3[2] = p0; - - p3 = e[2]*B[3] - e[3]*B[2]; - p2 = -e[2]*B[2] - e[3]*B[3]; - - d0[2] = p3; - d1[1] = - p3; - d2[2] = p2; - d3[1] = p2; - - p1 = e[0]*B[1] - e[1]*B[0]; - p0 = -e[0]*B[0] - e[1]*B[1]; - - d0[3] = p1; - d1[0] = - p1; - d2[3] = p0; - d3[0] = p0; - - B -= 8; - e -= 8; - d0 += 4; - d2 += 4; - d1 -= 4; - d3 -= 4; - } - } - - temp_alloc_restore(f,save_point); -} - -#if 0 -// this is the original version of the above code, if you want to optimize it from scratch -void inverse_mdct_naive(float *buffer, int n) -{ - float s; - float A[1 << 12], B[1 << 12], C[1 << 11]; - int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; - int n3_4 = n - n4, ld; - // how can they claim this only uses N words?! - // oh, because they're only used sparsely, whoops - float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13]; - // set up twiddle factors - - for (k=k2=0; k < n4; ++k,k2+=2) { - A[k2 ] = (float) cos(4*k*M_PI/n); - A[k2+1] = (float) -sin(4*k*M_PI/n); - B[k2 ] = (float) cos((k2+1)*M_PI/n/2); - B[k2+1] = (float) sin((k2+1)*M_PI/n/2); - } - for (k=k2=0; k < n8; ++k,k2+=2) { - C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); - C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); - } - - // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" - // Note there are bugs in that pseudocode, presumably due to them attempting - // to rename the arrays nicely rather than representing the way their actual - // implementation bounces buffers back and forth. As a result, even in the - // "some formulars corrected" version, a direct implementation fails. These - // are noted below as "paper bug". - - // copy and reflect spectral data - for (k=0; k < n2; ++k) u[k] = buffer[k]; - for ( ; k < n ; ++k) u[k] = -buffer[n - k - 1]; - // kernel from paper - // step 1 - for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) { - v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2] - (u[k4+2] - u[n-k4-3])*A[k2+1]; - v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2]; - } - // step 2 - for (k=k4=0; k < n8; k+=1, k4+=4) { - w[n2+3+k4] = v[n2+3+k4] + v[k4+3]; - w[n2+1+k4] = v[n2+1+k4] + v[k4+1]; - w[k4+3] = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4]; - w[k4+1] = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4]; - } - // step 3 - ld = ilog(n) - 1; // ilog is off-by-one from normal definitions - for (l=0; l < ld-3; ++l) { - int k0 = n >> (l+2), k1 = 1 << (l+3); - int rlim = n >> (l+4), r4, r; - int s2lim = 1 << (l+2), s2; - for (r=r4=0; r < rlim; r4+=4,++r) { - for (s2=0; s2 < s2lim; s2+=2) { - u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4]; - u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4]; - u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1] - - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1]; - u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1] - + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1]; - } - } - if (l+1 < ld-3) { - // paper bug: ping-ponging of u&w here is omitted - memcpy(w, u, sizeof(u)); - } - } - - // step 4 - for (i=0; i < n8; ++i) { - int j = bit_reverse(i) >> (32-ld+3); - assert(j < n8); - if (i == j) { - // paper bug: original code probably swapped in place; if copying, - // need to directly copy in this case - int i8 = i << 3; - v[i8+1] = u[i8+1]; - v[i8+3] = u[i8+3]; - v[i8+5] = u[i8+5]; - v[i8+7] = u[i8+7]; - } else if (i < j) { - int i8 = i << 3, j8 = j << 3; - v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1]; - v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3]; - v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5]; - v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7]; - } - } - // step 5 - for (k=0; k < n2; ++k) { - w[k] = v[k*2+1]; - } - // step 6 - for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) { - u[n-1-k2] = w[k4]; - u[n-2-k2] = w[k4+1]; - u[n3_4 - 1 - k2] = w[k4+2]; - u[n3_4 - 2 - k2] = w[k4+3]; - } - // step 7 - for (k=k2=0; k < n8; ++k, k2 += 2) { - v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; - v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; - v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; - v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; - } - // step 8 - for (k=k2=0; k < n4; ++k,k2 += 2) { - X[k] = v[k2+n2]*B[k2 ] + v[k2+1+n2]*B[k2+1]; - X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2 ]; - } - - // decode kernel to output - // determined the following value experimentally - // (by first figuring out what made inverse_mdct_slow work); then matching that here - // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?) - s = 0.5; // theoretically would be n4 - - // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code, - // so it needs to use the "old" B values to behave correctly, or else - // set s to 1.0 ]]] - for (i=0; i < n4 ; ++i) buffer[i] = s * X[i+n4]; - for ( ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1]; - for ( ; i < n ; ++i) buffer[i] = -s * X[i - n3_4]; -} -#endif - -static float *get_window(vorb *f, int len) -{ - len <<= 1; - if (len == f->blocksize_0) return f->window[0]; - if (len == f->blocksize_1) return f->window[1]; - assert(0); - return NULL; -} - -#ifndef STB_VORBIS_NO_DEFER_FLOOR -typedef int16 YTYPE; -#else -typedef int YTYPE; -#endif -static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag) -{ - int n2 = n >> 1; - int s = map->chan[i].mux, floor; - floor = map->submap_floor[s]; - if (f->floor_types[floor] == 0) { - return error(f, VORBIS_invalid_stream); - } else { - Floor1 *g = &f->floor_config[floor].floor1; - int j,q; - int lx = 0, ly = finalY[0] * g->floor1_multiplier; - for (q=1; q < g->values; ++q) { - j = g->sorted_order[q]; - #ifndef STB_VORBIS_NO_DEFER_FLOOR - if (finalY[j] >= 0) - #else - if (step2_flag[j]) - #endif - { - int hy = finalY[j] * g->floor1_multiplier; - int hx = g->Xlist[j]; - draw_line(target, lx,ly, hx,hy, n2); - lx = hx, ly = hy; - } - } - if (lx < n2) - // optimization of: draw_line(target, lx,ly, n,ly, n2); - for (j=lx; j < n2; ++j) - LINE_OP(target[j], inverse_db_table[ly]); - } - return TRUE; -} - -// The meaning of "left" and "right" -// -// For a given frame: -// we compute samples from 0..n -// window_center is n/2 -// we'll window and mix the samples from left_start to left_end with data from the previous frame -// all of the samples from left_end to right_start can be output without mixing; however, -// this interval is 0-length except when transitioning between short and long frames -// all of the samples from right_start to right_end need to be mixed with the next frame, -// which we don't have, so those get saved in a buffer -// frame N's right_end-right_start, the number of samples to mix with the next frame, -// has to be the same as frame N+1's left_end-left_start (which they are by -// construction) - -static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) -{ - Mode *m; - int i, n, prev, next, window_center; - f->channel_buffer_start = f->channel_buffer_end = 0; - - retry: - if (f->eof) return FALSE; - if (!maybe_start_packet(f)) - return FALSE; - // check packet type - if (get_bits(f,1) != 0) { - if (IS_PUSH_MODE(f)) - return error(f,VORBIS_bad_packet_type); - while (EOP != get8_packet(f)); - goto retry; - } - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - - i = get_bits(f, ilog(f->mode_count-1)); - if (i == EOP) return FALSE; - if (i >= f->mode_count) return FALSE; - *mode = i; - m = f->mode_config + i; - if (m->blockflag) { - n = f->blocksize_1; - prev = get_bits(f,1); - next = get_bits(f,1); - } else { - prev = next = 0; - n = f->blocksize_0; - } - -// WINDOWING - - window_center = n >> 1; - if (m->blockflag && !prev) { - *p_left_start = (n - f->blocksize_0) >> 2; - *p_left_end = (n + f->blocksize_0) >> 2; - } else { - *p_left_start = 0; - *p_left_end = window_center; - } - if (m->blockflag && !next) { - *p_right_start = (n*3 - f->blocksize_0) >> 2; - *p_right_end = (n*3 + f->blocksize_0) >> 2; - } else { - *p_right_start = window_center; - *p_right_end = n; - } - return TRUE; -} - -static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left) -{ - Mapping *map; - int i,j,k,n,n2; - int zero_channel[256]; - int really_zero_channel[256]; - -// WINDOWING - - n = f->blocksize[m->blockflag]; - map = &f->mapping[m->mapping]; - -// FLOORS - n2 = n >> 1; - - stb_prof(1); - for (i=0; i < f->channels; ++i) { - int s = map->chan[i].mux, floor; - zero_channel[i] = FALSE; - floor = map->submap_floor[s]; - if (f->floor_types[floor] == 0) { - return error(f, VORBIS_invalid_stream); - } else { - Floor1 *g = &f->floor_config[floor].floor1; - if (get_bits(f, 1)) { - short *finalY; - uint8 step2_flag[256]; - static int range_list[4] = { 256, 128, 86, 64 }; - int range = range_list[g->floor1_multiplier-1]; - int offset = 2; - finalY = f->finalY[i]; - finalY[0] = get_bits(f, ilog(range)-1); - finalY[1] = get_bits(f, ilog(range)-1); - for (j=0; j < g->partitions; ++j) { - int pclass = g->partition_class_list[j]; - int cdim = g->class_dimensions[pclass]; - int cbits = g->class_subclasses[pclass]; - int csub = (1 << cbits)-1; - int cval = 0; - if (cbits) { - Codebook *c = f->codebooks + g->class_masterbooks[pclass]; - DECODE(cval,f,c); - } - for (k=0; k < cdim; ++k) { - int book = g->subclass_books[pclass][cval & csub]; - cval = cval >> cbits; - if (book >= 0) { - int temp; - Codebook *c = f->codebooks + book; - DECODE(temp,f,c); - finalY[offset++] = temp; - } else - finalY[offset++] = 0; - } - } - if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec - step2_flag[0] = step2_flag[1] = 1; - for (j=2; j < g->values; ++j) { - int low, high, pred, highroom, lowroom, room, val; - low = g->neighbors[j][0]; - high = g->neighbors[j][1]; - //neighbors(g->Xlist, j, &low, &high); - pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); - val = finalY[j]; - highroom = range - pred; - lowroom = pred; - if (highroom < lowroom) - room = highroom * 2; - else - room = lowroom * 2; - if (val) { - step2_flag[low] = step2_flag[high] = 1; - step2_flag[j] = 1; - if (val >= room) - if (highroom > lowroom) - finalY[j] = val - lowroom + pred; - else - finalY[j] = pred - val + highroom - 1; - else - if (val & 1) - finalY[j] = pred - ((val+1)>>1); - else - finalY[j] = pred + (val>>1); - } else { - step2_flag[j] = 0; - finalY[j] = pred; - } - } - -#ifdef STB_VORBIS_NO_DEFER_FLOOR - do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag); -#else - // defer final floor computation until _after_ residue - for (j=0; j < g->values; ++j) { - if (!step2_flag[j]) - finalY[j] = -1; - } -#endif - } else { - error: - zero_channel[i] = TRUE; - } - // So we just defer everything else to later - - // at this point we've decoded the floor into buffer - } - } - stb_prof(0); - // at this point we've decoded all floors - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - - // re-enable coupled channels if necessary - memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); - for (i=0; i < map->coupling_steps; ++i) - if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) { - zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; - } - -// RESIDUE DECODE - for (i=0; i < map->submaps; ++i) { - float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; - int r; - uint8 do_not_decode[256]; - int ch = 0; - for (j=0; j < f->channels; ++j) { - if (map->chan[j].mux == i) { - if (zero_channel[j]) { - do_not_decode[ch] = TRUE; - residue_buffers[ch] = NULL; - } else { - do_not_decode[ch] = FALSE; - residue_buffers[ch] = f->channel_buffers[j]; - } - ++ch; - } - } - r = map->submap_residue[i]; - decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); - } - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - -// INVERSE COUPLING - stb_prof(14); - for (i = map->coupling_steps-1; i >= 0; --i) { - int n2 = n >> 1; - float *m = f->channel_buffers[map->chan[i].magnitude]; - float *a = f->channel_buffers[map->chan[i].angle ]; - for (j=0; j < n2; ++j) { - float a2,m2; - if (m[j] > 0) - if (a[j] > 0) - m2 = m[j], a2 = m[j] - a[j]; - else - a2 = m[j], m2 = m[j] + a[j]; - else - if (a[j] > 0) - m2 = m[j], a2 = m[j] + a[j]; - else - a2 = m[j], m2 = m[j] - a[j]; - m[j] = m2; - a[j] = a2; - } - } - - // finish decoding the floors -#ifndef STB_VORBIS_NO_DEFER_FLOOR - stb_prof(15); - for (i=0; i < f->channels; ++i) { - if (really_zero_channel[i]) { - memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); - } else { - do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); - } - } -#else - for (i=0; i < f->channels; ++i) { - if (really_zero_channel[i]) { - memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); - } else { - for (j=0; j < n2; ++j) - f->channel_buffers[i][j] *= f->floor_buffers[i][j]; - } - } -#endif - -// INVERSE MDCT - stb_prof(16); - for (i=0; i < f->channels; ++i) - inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); - stb_prof(0); - - // this shouldn't be necessary, unless we exited on an error - // and want to flush to get to the next packet - flush_packet(f); - - if (f->first_decode) { - // assume we start so first non-discarded sample is sample 0 - // this isn't to spec, but spec would require us to read ahead - // and decode the size of all current frames--could be done, - // but presumably it's not a commonly used feature - f->current_loc = -n2; // start of first frame is positioned for discard - // we might have to discard samples "from" the next frame too, - // if we're lapping a large block then a small at the start? - f->discard_samples_deferred = n - right_end; - f->current_loc_valid = TRUE; - f->first_decode = FALSE; - } else if (f->discard_samples_deferred) { - left_start += f->discard_samples_deferred; - *p_left = left_start; - f->discard_samples_deferred = 0; - } else if (f->previous_length == 0 && f->current_loc_valid) { - // we're recovering from a seek... that means we're going to discard - // the samples from this packet even though we know our position from - // the last page header, so we need to update the position based on - // the discarded samples here - // but wait, the code below is going to add this in itself even - // on a discard, so we don't need to do it here... - } - - // check if we have ogg information about the sample # for this packet - if (f->last_seg_which == f->end_seg_with_known_loc) { - // if we have a valid current loc, and this is final: - if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { - uint32 current_end = f->known_loc_for_packet - (n-right_end); - // then let's infer the size of the (probably) short final frame - if (current_end < f->current_loc + right_end) { - if (current_end < f->current_loc) { - // negative truncation, that's impossible! - *len = 0; - } else { - *len = current_end - f->current_loc; - } - *len += left_start; - f->current_loc += *len; - return TRUE; - } - } - // otherwise, just set our sample loc - // guess that the ogg granule pos refers to the _middle_ of the - // last frame? - // set f->current_loc to the position of left_start - f->current_loc = f->known_loc_for_packet - (n2-left_start); - f->current_loc_valid = TRUE; - } - if (f->current_loc_valid) - f->current_loc += (right_start - left_start); - - if (f->alloc.alloc_buffer) - assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); - *len = right_end; // ignore samples after the window goes to 0 - return TRUE; -} - -static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right) -{ - int mode, left_end, right_end; - if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; - return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); -} - -static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) -{ - int prev,i,j; - // we use right&left (the start of the right- and left-window sin()-regions) - // to determine how much to return, rather than inferring from the rules - // (same result, clearer code); 'left' indicates where our sin() window - // starts, therefore where the previous window's right edge starts, and - // therefore where to start mixing from the previous buffer. 'right' - // indicates where our sin() ending-window starts, therefore that's where - // we start saving, and where our returned-data ends. - - // mixin from previous window - if (f->previous_length) { - int i,j, n = f->previous_length; - float *w = get_window(f, n); - for (i=0; i < f->channels; ++i) { - for (j=0; j < n; ++j) - f->channel_buffers[i][left+j] = - f->channel_buffers[i][left+j]*w[ j] + - f->previous_window[i][ j]*w[n-1-j]; - } - } - - prev = f->previous_length; - - // last half of this data becomes previous window - f->previous_length = len - right; - - // @OPTIMIZE: could avoid this copy by double-buffering the - // output (flipping previous_window with channel_buffers), but - // then previous_window would have to be 2x as large, and - // channel_buffers couldn't be temp mem (although they're NOT - // currently temp mem, they could be (unless we want to level - // performance by spreading out the computation)) - for (i=0; i < f->channels; ++i) - for (j=0; right+j < len; ++j) - f->previous_window[i][j] = f->channel_buffers[i][right+j]; - - if (!prev) - // there was no previous packet, so this data isn't valid... - // this isn't entirely true, only the would-have-overlapped data - // isn't valid, but this seems to be what the spec requires - return 0; - - // truncate a short frame - if (len < right) right = len; - - f->samples_output += right-left; - - return right - left; -} - -static void vorbis_pump_first_frame(stb_vorbis *f) -{ - int len, right, left; - if (vorbis_decode_packet(f, &len, &left, &right)) - vorbis_finish_frame(f, len, left, right); -} - -#ifndef STB_VORBIS_NO_PUSHDATA_API -static int is_whole_packet_present(stb_vorbis *f, int end_page) -{ - // make sure that we have the packet available before continuing... - // this requires a full ogg parse, but we know we can fetch from f->stream - - // instead of coding this out explicitly, we could save the current read state, - // read the next packet with get8() until end-of-packet, check f->eof, then - // reset the state? but that would be slower, esp. since we'd have over 256 bytes - // of state to restore (primarily the page segment table) - - int s = f->next_seg, first = TRUE; - uint8 *p = f->stream; - - if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag - for (; s < f->segment_count; ++s) { - p += f->segments[s]; - if (f->segments[s] < 255) // stop at first short segment - break; - } - // either this continues, or it ends it... - if (end_page) - if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream); - if (s == f->segment_count) - s = -1; // set 'crosses page' flag - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - first = FALSE; - } - for (; s == -1;) { - uint8 *q; - int n; - - // check that we have the page header ready - if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); - // validate the page - if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); - if (p[4] != 0) return error(f, VORBIS_invalid_stream); - if (first) { // the first segment must NOT have 'continued_packet', later ones MUST - if (f->previous_length) - if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); - // if no previous length, we're resynching, so we can come in on a continued-packet, - // which we'll just drop - } else { - if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); - } - n = p[26]; // segment counts - q = p+27; // q points to segment table - p = q + n; // advance past header - // make sure we've read the segment table - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - for (s=0; s < n; ++s) { - p += q[s]; - if (q[s] < 255) - break; - } - if (end_page) - if (s < n-1) return error(f, VORBIS_invalid_stream); - if (s == n) - s = -1; // set 'crosses page' flag - if (p > f->stream_end) return error(f, VORBIS_need_more_data); - first = FALSE; - } - return TRUE; -} -#endif // !STB_VORBIS_NO_PUSHDATA_API - -static int start_decoder(vorb *f) -{ - uint8 header[6], x,y; - int len,i,j,k, max_submaps = 0; - int longest_floorlist=0; - - // first page, first packet - - if (!start_page(f)) return FALSE; - // validate page flag - if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); - if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); - if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); - // check for expected packet length - if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); - if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page); - // read packet - // check packet header - if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); - if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); - if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); - // vorbis_version - if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); - f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page); - if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); - f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); - get32(f); // bitrate_maximum - get32(f); // bitrate_nominal - get32(f); // bitrate_minimum - x = get8(f); - { int log0,log1; - log0 = x & 15; - log1 = x >> 4; - f->blocksize_0 = 1 << log0; - f->blocksize_1 = 1 << log1; - if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); - if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); - if (log0 > log1) return error(f, VORBIS_invalid_setup); - } - - // framing_flag - x = get8(f); - if (!(x & 1)) return error(f, VORBIS_invalid_first_page); - - // second packet! - if (!start_page(f)) return FALSE; - - if (!start_packet(f)) return FALSE; - do { - len = next_segment(f); - skip(f, len); - f->bytes_in_seg = 0; - } while (len); - - // third packet! - if (!start_packet(f)) return FALSE; - - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (IS_PUSH_MODE(f)) { - if (!is_whole_packet_present(f, TRUE)) { - // convert error in ogg header to write type - if (f->error == VORBIS_invalid_stream) - f->error = VORBIS_invalid_setup; - return FALSE; - } - } - #endif - - crc32_init(); // always init it, to avoid multithread race conditions - - if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); - for (i=0; i < 6; ++i) header[i] = get8_packet(f); - if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); - - // codebooks - - f->codebook_count = get_bits(f,8) + 1; - f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); - if (f->codebooks == NULL) return error(f, VORBIS_outofmem); - memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); - for (i=0; i < f->codebook_count; ++i) { - uint32 *values; - int ordered, sorted_count; - int total=0; - uint8 *lengths; - Codebook *c = f->codebooks+i; - x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); - x = get_bits(f, 8); - c->dimensions = (get_bits(f, 8)<<8) + x; - x = get_bits(f, 8); - y = get_bits(f, 8); - c->entries = (get_bits(f, 8)<<16) + (y<<8) + x; - ordered = get_bits(f,1); - c->sparse = ordered ? 0 : get_bits(f,1); - - if (c->sparse) - lengths = (uint8 *) setup_temp_malloc(f, c->entries); - else - lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); - - if (!lengths) return error(f, VORBIS_outofmem); - - if (ordered) { - int current_entry = 0; - int current_length = get_bits(f,5) + 1; - while (current_entry < c->entries) { - int limit = c->entries - current_entry; - int n = get_bits(f, ilog(limit)); - if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } - memset(lengths + current_entry, current_length, n); - current_entry += n; - ++current_length; - } - } else { - for (j=0; j < c->entries; ++j) { - int present = c->sparse ? get_bits(f,1) : 1; - if (present) { - lengths[j] = get_bits(f, 5) + 1; - ++total; - } else { - lengths[j] = NO_CODE; - } - } - } - - if (c->sparse && total >= c->entries >> 2) { - // convert sparse items to non-sparse! - if (c->entries > (int) f->setup_temp_memory_required) - f->setup_temp_memory_required = c->entries; - - c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); - memcpy(c->codeword_lengths, lengths, c->entries); - setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! - lengths = c->codeword_lengths; - c->sparse = 0; - } - - // compute the size of the sorted tables - if (c->sparse) { - sorted_count = total; - } else { - sorted_count = 0; - #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH - for (j=0; j < c->entries; ++j) - if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) - ++sorted_count; - #endif - } - - c->sorted_entries = sorted_count; - values = NULL; - - if (!c->sparse) { - c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); - if (!c->codewords) return error(f, VORBIS_outofmem); - } else { - unsigned int size; - if (c->sorted_entries) { - c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries); - if (!c->codeword_lengths) return error(f, VORBIS_outofmem); - c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); - if (!c->codewords) return error(f, VORBIS_outofmem); - values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); - if (!values) return error(f, VORBIS_outofmem); - } - size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; - if (size > f->setup_temp_memory_required) - f->setup_temp_memory_required = size; - } - - if (!compute_codewords(c, lengths, c->entries, values)) { - if (c->sparse) setup_temp_free(f, values, 0); - return error(f, VORBIS_invalid_setup); - } - - if (c->sorted_entries) { - // allocate an extra slot for sentinels - c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); - // allocate an extra slot at the front so that c->sorted_values[-1] is defined - // so that we can catch that case without an extra if - c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); - if (c->sorted_values) { ++c->sorted_values; c->sorted_values[-1] = -1; } - compute_sorted_huffman(c, lengths, values); - } - - if (c->sparse) { - setup_temp_free(f, values, sizeof(*values)*c->sorted_entries); - setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries); - setup_temp_free(f, lengths, c->entries); - c->codewords = NULL; - } - - compute_accelerated_huffman(c); - - c->lookup_type = get_bits(f, 4); - if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); - if (c->lookup_type > 0) { - uint16 *mults; - c->minimum_value = float32_unpack(get_bits(f, 32)); - c->delta_value = float32_unpack(get_bits(f, 32)); - c->value_bits = get_bits(f, 4)+1; - c->sequence_p = get_bits(f,1); - if (c->lookup_type == 1) { - c->lookup_values = lookup1_values(c->entries, c->dimensions); - } else { - c->lookup_values = c->entries * c->dimensions; - } - mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); - if (mults == NULL) return error(f, VORBIS_outofmem); - for (j=0; j < (int) c->lookup_values; ++j) { - int q = get_bits(f, c->value_bits); - if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); } - mults[j] = q; - } - -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - if (c->lookup_type == 1) { - int len, sparse = c->sparse; - // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop - if (sparse) { - if (c->sorted_entries == 0) goto skip; - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); - } else - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); - if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } - len = sparse ? c->sorted_entries : c->entries; - for (j=0; j < len; ++j) { - int z = sparse ? c->sorted_values[j] : j, div=1; - for (k=0; k < c->dimensions; ++k) { - int off = (z / div) % c->lookup_values; - c->multiplicands[j*c->dimensions + k] = - #ifndef STB_VORBIS_CODEBOOK_FLOATS - mults[off]; - #else - mults[off]*c->delta_value + c->minimum_value; - // in this case (and this case only) we could pre-expand c->sequence_p, - // and throw away the decode logic for it; have to ALSO do - // it in the case below, but it can only be done if - // STB_VORBIS_CODEBOOK_FLOATS - // !STB_VORBIS_DIVIDES_IN_CODEBOOK - #endif - div *= c->lookup_values; - } - } - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); - c->lookup_type = 2; - } - else -#endif - { - c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); - #ifndef STB_VORBIS_CODEBOOK_FLOATS - memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values); - #else - for (j=0; j < (int) c->lookup_values; ++j) - c->multiplicands[j] = mults[j] * c->delta_value + c->minimum_value; - #endif - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); - } -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK - skip:; -#endif - - #ifdef STB_VORBIS_CODEBOOK_FLOATS - if (c->lookup_type == 2 && c->sequence_p) { - for (j=1; j < (int) c->lookup_values; ++j) - c->multiplicands[j] = c->multiplicands[j-1]; - c->sequence_p = 0; - } - #endif - } - } - - // time domain transfers (notused) - - x = get_bits(f, 6) + 1; - for (i=0; i < x; ++i) { - uint32 z = get_bits(f, 16); - if (z != 0) return error(f, VORBIS_invalid_setup); - } - - // Floors - f->floor_count = get_bits(f, 6)+1; - f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); - for (i=0; i < f->floor_count; ++i) { - f->floor_types[i] = get_bits(f, 16); - if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); - if (f->floor_types[i] == 0) { - Floor0 *g = &f->floor_config[i].floor0; - g->order = get_bits(f,8); - g->rate = get_bits(f,16); - g->bark_map_size = get_bits(f,16); - g->amplitude_bits = get_bits(f,6); - g->amplitude_offset = get_bits(f,8); - g->number_of_books = get_bits(f,4) + 1; - for (j=0; j < g->number_of_books; ++j) - g->book_list[j] = get_bits(f,8); - return error(f, VORBIS_feature_not_supported); - } else { - Point p[31*8+2]; - Floor1 *g = &f->floor_config[i].floor1; - int max_class = -1; - g->partitions = get_bits(f, 5); - for (j=0; j < g->partitions; ++j) { - g->partition_class_list[j] = get_bits(f, 4); - if (g->partition_class_list[j] > max_class) - max_class = g->partition_class_list[j]; - } - for (j=0; j <= max_class; ++j) { - g->class_dimensions[j] = get_bits(f, 3)+1; - g->class_subclasses[j] = get_bits(f, 2); - if (g->class_subclasses[j]) { - g->class_masterbooks[j] = get_bits(f, 8); - if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } - for (k=0; k < 1 << g->class_subclasses[j]; ++k) { - g->subclass_books[j][k] = get_bits(f,8)-1; - if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } - } - g->floor1_multiplier = get_bits(f,2)+1; - g->rangebits = get_bits(f,4); - g->Xlist[0] = 0; - g->Xlist[1] = 1 << g->rangebits; - g->values = 2; - for (j=0; j < g->partitions; ++j) { - int c = g->partition_class_list[j]; - for (k=0; k < g->class_dimensions[c]; ++k) { - g->Xlist[g->values] = get_bits(f, g->rangebits); - ++g->values; - } - } - // precompute the sorting - for (j=0; j < g->values; ++j) { - p[j].x = g->Xlist[j]; - p[j].y = j; - } - qsort(p, g->values, sizeof(p[0]), point_compare); - for (j=0; j < g->values; ++j) - g->sorted_order[j] = (uint8) p[j].y; - // precompute the neighbors - for (j=2; j < g->values; ++j) { - int low,hi; - neighbors(g->Xlist, j, &low,&hi); - g->neighbors[j][0] = low; - g->neighbors[j][1] = hi; - } - - if (g->values > longest_floorlist) - longest_floorlist = g->values; - } - } - - // Residue - f->residue_count = get_bits(f, 6)+1; - f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(*f->residue_config)); - for (i=0; i < f->residue_count; ++i) { - uint8 residue_cascade[64]; - Residue *r = f->residue_config+i; - f->residue_types[i] = get_bits(f, 16); - if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); - r->begin = get_bits(f, 24); - r->end = get_bits(f, 24); - r->part_size = get_bits(f,24)+1; - r->classifications = get_bits(f,6)+1; - r->classbook = get_bits(f,8); - for (j=0; j < r->classifications; ++j) { - uint8 high_bits=0; - uint8 low_bits=get_bits(f,3); - if (get_bits(f,1)) - high_bits = get_bits(f,5); - residue_cascade[j] = high_bits*8 + low_bits; - } - r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); - for (j=0; j < r->classifications; ++j) { - for (k=0; k < 8; ++k) { - if (residue_cascade[j] & (1 << k)) { - r->residue_books[j][k] = get_bits(f, 8); - if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); - } else { - r->residue_books[j][k] = -1; - } - } - } - // precompute the classifications[] array to avoid inner-loop mod/divide - // call it 'classdata' since we already have r->classifications - r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); - if (!r->classdata) return error(f, VORBIS_outofmem); - memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); - for (j=0; j < f->codebooks[r->classbook].entries; ++j) { - int classwords = f->codebooks[r->classbook].dimensions; - int temp = j; - r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); - for (k=classwords-1; k >= 0; --k) { - r->classdata[j][k] = temp % r->classifications; - temp /= r->classifications; - } - } - } - - f->mapping_count = get_bits(f,6)+1; - f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); - for (i=0; i < f->mapping_count; ++i) { - Mapping *m = f->mapping + i; - int mapping_type = get_bits(f,16); - if (mapping_type != 0) return error(f, VORBIS_invalid_setup); - m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); - if (get_bits(f,1)) - m->submaps = get_bits(f,4)+1; - else - m->submaps = 1; - if (m->submaps > max_submaps) - max_submaps = m->submaps; - if (get_bits(f,1)) { - m->coupling_steps = get_bits(f,8)+1; - for (k=0; k < m->coupling_steps; ++k) { - m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); - m->chan[k].angle = get_bits(f, ilog(f->channels-1)); - if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); - if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); - if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); - } - } else - m->coupling_steps = 0; - - // reserved field - if (get_bits(f,2)) return error(f, VORBIS_invalid_setup); - if (m->submaps > 1) { - for (j=0; j < f->channels; ++j) { - m->chan[j].mux = get_bits(f, 4); - if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); - } - } else - // @SPECIFICATION: this case is missing from the spec - for (j=0; j < f->channels; ++j) - m->chan[j].mux = 0; - - for (j=0; j < m->submaps; ++j) { - get_bits(f,8); // discard - m->submap_floor[j] = get_bits(f,8); - m->submap_residue[j] = get_bits(f,8); - if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); - if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); - } - } - - // Modes - f->mode_count = get_bits(f, 6)+1; - for (i=0; i < f->mode_count; ++i) { - Mode *m = f->mode_config+i; - m->blockflag = get_bits(f,1); - m->windowtype = get_bits(f,16); - m->transformtype = get_bits(f,16); - m->mapping = get_bits(f,8); - if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); - if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); - if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); - } - - flush_packet(f); - - f->previous_length = 0; - - for (i=0; i < f->channels; ++i) { - f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); - f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); - f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); - #ifdef STB_VORBIS_NO_DEFER_FLOOR - f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); - #endif - } - - if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; - if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; - f->blocksize[0] = f->blocksize_0; - f->blocksize[1] = f->blocksize_1; - -#ifdef STB_VORBIS_DIVIDE_TABLE - if (integer_divide_table[1][1]==0) - for (i=0; i < DIVTAB_NUMER; ++i) - for (j=1; j < DIVTAB_DENOM; ++j) - integer_divide_table[i][j] = i / j; -#endif - - // compute how much temporary memory is needed - - // 1. - { - uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); - uint32 classify_mem; - int i,max_part_read=0; - for (i=0; i < f->residue_count; ++i) { - Residue *r = f->residue_config + i; - int n_read = r->end - r->begin; - int part_read = n_read / r->part_size; - if (part_read > max_part_read) - max_part_read = part_read; - } - #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE - classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *)); - #else - classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); - #endif - - f->temp_memory_required = classify_mem; - if (imdct_mem > f->temp_memory_required) - f->temp_memory_required = imdct_mem; - } - - f->first_decode = TRUE; - - if (f->alloc.alloc_buffer) { - assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); - // check if there's enough temp memory so we don't error later - if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset) - return error(f, VORBIS_outofmem); - } - - f->first_audio_page_offset = stb_vorbis_get_file_offset(f); - - return TRUE; -} - -static void vorbis_deinit(stb_vorbis *p) -{ - int i,j; - for (i=0; i < p->residue_count; ++i) { - Residue *r = p->residue_config+i; - if (r->classdata) { - for (j=0; j < p->codebooks[r->classbook].entries; ++j) - setup_free(p, r->classdata[j]); - setup_free(p, r->classdata); - } - setup_free(p, r->residue_books); - } - - if (p->codebooks) { - for (i=0; i < p->codebook_count; ++i) { - Codebook *c = p->codebooks + i; - setup_free(p, c->codeword_lengths); - setup_free(p, c->multiplicands); - setup_free(p, c->codewords); - setup_free(p, c->sorted_codewords); - // c->sorted_values[-1] is the first entry in the array - setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL); - } - setup_free(p, p->codebooks); - } - setup_free(p, p->floor_config); - setup_free(p, p->residue_config); - for (i=0; i < p->mapping_count; ++i) - setup_free(p, p->mapping[i].chan); - setup_free(p, p->mapping); - for (i=0; i < p->channels; ++i) { - setup_free(p, p->channel_buffers[i]); - setup_free(p, p->previous_window[i]); - #ifdef STB_VORBIS_NO_DEFER_FLOOR - setup_free(p, p->floor_buffers[i]); - #endif - setup_free(p, p->finalY[i]); - } - for (i=0; i < 2; ++i) { - setup_free(p, p->A[i]); - setup_free(p, p->B[i]); - setup_free(p, p->C[i]); - setup_free(p, p->window[i]); - setup_free(p, p->bit_reverse[i]); - } - #ifndef STB_VORBIS_NO_STDIO - if (p->close_on_free) fclose(p->f); - #endif -} - -void stb_vorbis_close(stb_vorbis *p) -{ - if (p == NULL) return; - vorbis_deinit(p); - setup_free(p,p); -} - -static void vorbis_init(stb_vorbis *p, stb_vorbis_alloc *z) -{ - memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start - if (z) { - p->alloc = *z; - p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3; - p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; - } - p->eof = 0; - p->error = VORBIS__no_error; - p->stream = NULL; - p->codebooks = NULL; - p->page_crc_tests = -1; - #ifndef STB_VORBIS_NO_STDIO - p->close_on_free = FALSE; - p->f = NULL; - #endif -} - -int stb_vorbis_get_sample_offset(stb_vorbis *f) -{ - if (f->current_loc_valid) - return f->current_loc; - else - return -1; -} - -stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) -{ - stb_vorbis_info d; - d.channels = f->channels; - d.sample_rate = f->sample_rate; - d.setup_memory_required = f->setup_memory_required; - d.setup_temp_memory_required = f->setup_temp_memory_required; - d.temp_memory_required = f->temp_memory_required; - d.max_frame_size = f->blocksize_1 >> 1; - return d; -} - -int stb_vorbis_get_error(stb_vorbis *f) -{ - int e = f->error; - f->error = VORBIS__no_error; - return e; -} - -static stb_vorbis * vorbis_alloc(stb_vorbis *f) -{ - stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p)); - return p; -} - -#ifndef STB_VORBIS_NO_PUSHDATA_API - -void stb_vorbis_flush_pushdata(stb_vorbis *f) -{ - f->previous_length = 0; - f->page_crc_tests = 0; - f->discard_samples_deferred = 0; - f->current_loc_valid = FALSE; - f->first_decode = FALSE; - f->samples_output = 0; - f->channel_buffer_start = 0; - f->channel_buffer_end = 0; -} - -static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) -{ - int i,n; - for (i=0; i < f->page_crc_tests; ++i) - f->scan[i].bytes_done = 0; - - // if we have room for more scans, search for them first, because - // they may cause us to stop early if their header is incomplete - if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) { - if (data_len < 4) return 0; - data_len -= 3; // need to look for 4-byte sequence, so don't miss - // one that straddles a boundary - for (i=0; i < data_len; ++i) { - if (data[i] == 0x4f) { - if (0==memcmp(data+i, ogg_page_header, 4)) { - int j,len; - uint32 crc; - // make sure we have the whole page header - if (i+26 >= data_len || i+27+data[i+26] >= data_len) { - // only read up to this page start, so hopefully we'll - // have the whole page header start next time - data_len = i; - break; - } - // ok, we have it all; compute the length of the page - len = 27 + data[i+26]; - for (j=0; j < data[i+26]; ++j) - len += data[i+27+j]; - // scan everything up to the embedded crc (which we must 0) - crc = 0; - for (j=0; j < 22; ++j) - crc = crc32_update(crc, data[i+j]); - // now process 4 0-bytes - for ( ; j < 26; ++j) - crc = crc32_update(crc, 0); - // len is the total number of bytes we need to scan - n = f->page_crc_tests++; - f->scan[n].bytes_left = len-j; - f->scan[n].crc_so_far = crc; - f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24); - // if the last frame on a page is continued to the next, then - // we can't recover the sample_loc immediately - if (data[i+27+data[i+26]-1] == 255) - f->scan[n].sample_loc = ~0; - else - f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24); - f->scan[n].bytes_done = i+j; - if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) - break; - // keep going if we still have room for more - } - } - } - } - - for (i=0; i < f->page_crc_tests;) { - uint32 crc; - int j; - int n = f->scan[i].bytes_done; - int m = f->scan[i].bytes_left; - if (m > data_len - n) m = data_len - n; - // m is the bytes to scan in the current chunk - crc = f->scan[i].crc_so_far; - for (j=0; j < m; ++j) - crc = crc32_update(crc, data[n+j]); - f->scan[i].bytes_left -= m; - f->scan[i].crc_so_far = crc; - if (f->scan[i].bytes_left == 0) { - // does it match? - if (f->scan[i].crc_so_far == f->scan[i].goal_crc) { - // Houston, we have page - data_len = n+m; // consumption amount is wherever that scan ended - f->page_crc_tests = -1; // drop out of page scan mode - f->previous_length = 0; // decode-but-don't-output one frame - f->next_seg = -1; // start a new page - f->current_loc = f->scan[i].sample_loc; // set the current sample location - // to the amount we'd have decoded had we decoded this page - f->current_loc_valid = f->current_loc != ~0U; - return data_len; - } - // delete entry - f->scan[i] = f->scan[--f->page_crc_tests]; - } else { - ++i; - } - } - - return data_len; -} - -// return value: number of bytes we used -int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, // the file we're decoding - uint8 *data, int data_len, // the memory available for decoding - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples - ) -{ - int i; - int len,right,left; - - if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - - if (f->page_crc_tests >= 0) { - *samples = 0; - return vorbis_search_for_page_pushdata(f, data, data_len); - } - - f->stream = data; - f->stream_end = data + data_len; - f->error = VORBIS__no_error; - - // check that we have the entire packet in memory - if (!is_whole_packet_present(f, FALSE)) { - *samples = 0; - return 0; - } - - if (!vorbis_decode_packet(f, &len, &left, &right)) { - // save the actual error we encountered - enum STBVorbisError error = f->error; - if (error == VORBIS_bad_packet_type) { - // flush and resynch - f->error = VORBIS__no_error; - while (get8_packet(f) != EOP) - if (f->eof) break; - *samples = 0; - return f->stream - data; - } - if (error == VORBIS_continued_packet_flag_invalid) { - if (f->previous_length == 0) { - // we may be resynching, in which case it's ok to hit one - // of these; just discard the packet - f->error = VORBIS__no_error; - while (get8_packet(f) != EOP) - if (f->eof) break; - *samples = 0; - return f->stream - data; - } - } - // if we get an error while parsing, what to do? - // well, it DEFINITELY won't work to continue from where we are! - stb_vorbis_flush_pushdata(f); - // restore the error that actually made us bail - f->error = error; - *samples = 0; - return 1; - } - - // success! - len = vorbis_finish_frame(f, len, left, right); - for (i=0; i < f->channels; ++i) - f->outputs[i] = f->channel_buffers[i] + left; - - if (channels) *channels = f->channels; - *samples = len; - *output = f->outputs; - return f->stream - data; -} - -stb_vorbis *stb_vorbis_open_pushdata( - unsigned char *data, int data_len, // the memory available for decoding - int *data_used, // only defined if result is not NULL - int *error, stb_vorbis_alloc *alloc) -{ - stb_vorbis *f, p; - vorbis_init(&p, alloc); - p.stream = data; - p.stream_end = data + data_len; - p.push_mode = TRUE; - if (!start_decoder(&p)) { - if (p.eof) - *error = VORBIS_need_more_data; - else - *error = p.error; - return NULL; - } - f = vorbis_alloc(&p); - if (f) { - *f = p; - *data_used = f->stream - data; - *error = 0; - return f; - } else { - vorbis_deinit(&p); - return NULL; - } -} -#endif // STB_VORBIS_NO_PUSHDATA_API - -unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) -{ - #ifndef STB_VORBIS_NO_PUSHDATA_API - if (f->push_mode) return 0; - #endif - if (USE_MEMORY(f)) return f->stream - f->stream_start; - #ifndef STB_VORBIS_NO_STDIO - return ftell(f->f) - f->f_start; - #endif -} - -#ifndef STB_VORBIS_NO_PULLDATA_API -// -// DATA-PULLING API -// - -static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) -{ - for(;;) { - int n; - if (f->eof) return 0; - n = get8(f); - if (n == 0x4f) { // page header - unsigned int retry_loc = stb_vorbis_get_file_offset(f); - int i; - // check if we're off the end of a file_section stream - if (retry_loc - 25 > f->stream_len) - return 0; - // check the rest of the header - for (i=1; i < 4; ++i) - if (get8(f) != ogg_page_header[i]) - break; - if (f->eof) return 0; - if (i == 4) { - uint8 header[27]; - uint32 i, crc, goal, len; - for (i=0; i < 4; ++i) - header[i] = ogg_page_header[i]; - for (; i < 27; ++i) - header[i] = get8(f); - if (f->eof) return 0; - if (header[4] != 0) goto invalid; - goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24); - for (i=22; i < 26; ++i) - header[i] = 0; - crc = 0; - for (i=0; i < 27; ++i) - crc = crc32_update(crc, header[i]); - len = 0; - for (i=0; i < header[26]; ++i) { - int s = get8(f); - crc = crc32_update(crc, s); - len += s; - } - if (len && f->eof) return 0; - for (i=0; i < len; ++i) - crc = crc32_update(crc, get8(f)); - // finished parsing probable page - if (crc == goal) { - // we could now check that it's either got the last - // page flag set, OR it's followed by the capture - // pattern, but I guess TECHNICALLY you could have - // a file with garbage between each ogg page and recover - // from it automatically? So even though that paranoia - // might decrease the chance of an invalid decode by - // another 2^32, not worth it since it would hose those - // invalid-but-useful files? - if (end) - *end = stb_vorbis_get_file_offset(f); - if (last) { - if (header[5] & 0x04) - *last = 1; - else - *last = 0; - } - set_file_offset(f, retry_loc-1); - return 1; - } - } - invalid: - // not a valid page, so rewind and look for next one - set_file_offset(f, retry_loc); - } - } -} - -// seek is implemented with 'interpolation search'--this is like -// binary search, but we use the data values to estimate the likely -// location of the data item (plus a bit of a bias so when the -// estimation is wrong we don't waste overly much time) - -#define SAMPLE_unknown 0xffffffff - - -// ogg vorbis, in its insane infinite wisdom, only provides -// information about the sample at the END of the page. -// therefore we COULD have the data we need in the current -// page, and not know it. we could just use the end location -// as our only knowledge for bounds, seek back, and eventually -// the binary search finds it. or we can try to be smart and -// not waste time trying to locate more pages. we try to be -// smart, since this data is already in memory anyway, so -// doing needless I/O would be crazy! -static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z) -{ - uint8 header[27], lacing[255]; - uint8 packet_type[255]; - int num_packet, packet_start; - int i,len; - uint32 samples; - - // record where the page starts - z->page_start = stb_vorbis_get_file_offset(f); - - // parse the header - getn(f, header, 27); - assert(header[0] == 'O' && header[1] == 'g' && header[2] == 'g' && header[3] == 'S'); - getn(f, lacing, header[26]); - - // determine the length of the payload - len = 0; - for (i=0; i < header[26]; ++i) - len += lacing[i]; - - // this implies where the page ends - z->page_end = z->page_start + 27 + header[26] + len; - - // read the last-decoded sample out of the data - z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 16); - - if (header[5] & 4) { - // if this is the last page, it's not possible to work - // backwards to figure out the first sample! whoops! fuck. - z->first_decoded_sample = SAMPLE_unknown; - set_file_offset(f, z->page_start); - return 1; - } - - // scan through the frames to determine the sample-count of each one... - // our goal is the sample # of the first fully-decoded sample on the - // page, which is the first decoded sample of the 2nd packet - - num_packet=0; - - packet_start = ((header[5] & 1) == 0); - - for (i=0; i < header[26]; ++i) { - if (packet_start) { - uint8 n,b; - if (lacing[i] == 0) goto bail; // trying to read from zero-length packet - n = get8(f); - // if bottom bit is non-zero, we've got corruption - if (n & 1) goto bail; - n >>= 1; - b = ilog(f->mode_count-1); - n &= (1 << b)-1; - if (n >= f->mode_count) goto bail; - packet_type[num_packet++] = f->mode_config[n].blockflag; - skip(f, lacing[i]-1); - } else - skip(f, lacing[i]); - packet_start = (lacing[i] < 255); - } - - // now that we know the sizes of all the pages, we can start determining - // how much sample data there is. - - samples = 0; - - // for the last packet, we step by its whole length, because the definition - // is that we encoded the end sample loc of the 'last packet completed', - // where 'completed' refers to packets being split, and we are left to guess - // what 'end sample loc' means. we assume it means ignoring the fact that - // the last half of the data is useless without windowing against the next - // packet... (so it's not REALLY complete in that sense) - if (num_packet > 1) - samples += f->blocksize[packet_type[num_packet-1]]; - - for (i=num_packet-2; i >= 1; --i) { - // now, for this packet, how many samples do we have that - // do not overlap the following packet? - if (packet_type[i] == 1) - if (packet_type[i+1] == 1) - samples += f->blocksize_1 >> 1; - else - samples += ((f->blocksize_1 - f->blocksize_0) >> 2) + (f->blocksize_0 >> 1); - else - samples += f->blocksize_0 >> 1; - } - // now, at this point, we've rewound to the very beginning of the - // _second_ packet. if we entirely discard the first packet after - // a seek, this will be exactly the right sample number. HOWEVER! - // we can't as easily compute this number for the LAST page. The - // only way to get the sample offset of the LAST page is to use - // the end loc from the previous page. But what that returns us - // is _exactly_ the place where we get our first non-overlapped - // sample. (I think. Stupid spec for being ambiguous.) So for - // consistency it's better to do that here, too. However, that - // will then require us to NOT discard all of the first frame we - // decode, in some cases, which means an even weirder frame size - // and extra code. what a fucking pain. - - // we're going to discard the first packet if we - // start the seek here, so we don't care about it. (we could actually - // do better; if the first packet is long, and the previous packet - // is short, there's actually data in the first half of the first - // packet that doesn't need discarding... but not worth paying the - // effort of tracking that of that here and in the seeking logic) - // except crap, if we infer it from the _previous_ packet's end - // location, we DO need to use that definition... and we HAVE to - // infer the start loc of the LAST packet from the previous packet's - // end location. fuck you, ogg vorbis. - - z->first_decoded_sample = z->last_decoded_sample - samples; - - // restore file state to where we were - set_file_offset(f, z->page_start); - return 1; - - // restore file state to where we were - bail: - set_file_offset(f, z->page_start); - return 0; -} - -static int vorbis_seek_frame_from_page(stb_vorbis *f, uint32 page_start, uint32 first_sample, uint32 target_sample, int fine) -{ - int left_start, left_end, right_start, right_end, mode,i; - int frame=0; - uint32 frame_start; - int frames_to_skip, data_to_skip; - - // first_sample is the sample # of the first sample that doesn't - // overlap the previous page... note that this requires us to - // _partially_ discard the first packet! bleh. - set_file_offset(f, page_start); - - f->next_seg = -1; // force page resync - - frame_start = first_sample; - // frame start is where the previous packet's last decoded sample - // was, which corresponds to left_end... EXCEPT if the previous - // packet was long and this packet is short? Probably a bug here. - - - // now, we can start decoding frames... we'll only FAKE decode them, - // until we find the frame that contains our sample; then we'll rewind, - // and try again - for (;;) { - int start; - - if (!vorbis_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) - return error(f, VORBIS_seek_failed); - - if (frame == 0) - start = left_end; - else - start = left_start; - - // the window starts at left_start; the last valid sample we generate - // before the next frame's window start is right_start-1 - if (target_sample < frame_start + right_start-start) - break; - - flush_packet(f); - if (f->eof) - return error(f, VORBIS_seek_failed); - - frame_start += right_start - start; - - ++frame; - } - - // ok, at this point, the sample we want is contained in frame #'frame' - - // to decode frame #'frame' normally, we have to decode the - // previous frame first... but if it's the FIRST frame of the page - // we can't. if it's the first frame, it means it falls in the part - // of the first frame that doesn't overlap either of the other frames. - // so, if we have to handle that case for the first frame, we might - // as well handle it for all of them, so: - if (target_sample > frame_start + (left_end - left_start)) { - // so what we want to do is go ahead and just immediately decode - // this frame, but then make it so the next get_frame_float() uses - // this already-decoded data? or do we want to go ahead and rewind, - // and leave a flag saying to skip the first N data? let's do that - frames_to_skip = frame; // if this is frame #1, skip 1 frame (#0) - data_to_skip = left_end - left_start; - } else { - // otherwise, we want to skip frames 0, 1, 2, ... frame-2 - // (which means frame-2+1 total frames) then decode frame-1, - // then leave frame pending - frames_to_skip = frame - 1; - assert(frames_to_skip >= 0); - data_to_skip = -1; - } - - set_file_offset(f, page_start); - f->next_seg = - 1; // force page resync - - for (i=0; i < frames_to_skip; ++i) { - maybe_start_packet(f); - flush_packet(f); - } - - if (data_to_skip >= 0) { - int i,j,n = f->blocksize_0 >> 1; - f->discard_samples_deferred = data_to_skip; - for (i=0; i < f->channels; ++i) - for (j=0; j < n; ++j) - f->previous_window[i][j] = 0; - f->previous_length = n; - frame_start += data_to_skip; - } else { - f->previous_length = 0; - vorbis_pump_first_frame(f); - } - - // at this point, the NEXT decoded frame will generate the desired sample - if (fine) { - // so if we're doing sample accurate streaming, we want to go ahead and decode it! - if (target_sample != frame_start) { - int n; - stb_vorbis_get_frame_float(f, &n, NULL); - assert(target_sample > frame_start); - assert(f->channel_buffer_start + (int) (target_sample-frame_start) < f->channel_buffer_end); - f->channel_buffer_start += (target_sample - frame_start); - } - } - - return 0; -} - -static int vorbis_seek_base(stb_vorbis *f, unsigned int sample_number, int fine) -{ - ProbedPage p[2],q; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - - // do we know the location of the last page? - if (f->p_last.page_start == 0) { - uint32 z = stb_vorbis_stream_length_in_samples(f); - if (z == 0) return error(f, VORBIS_cant_find_last_page); - } - - p[0] = f->p_first; - p[1] = f->p_last; - - if (sample_number >= f->p_last.last_decoded_sample) - sample_number = f->p_last.last_decoded_sample-1; - - if (sample_number < f->p_first.last_decoded_sample) { - vorbis_seek_frame_from_page(f, p[0].page_start, 0, sample_number, fine); - return 0; - } else { - int attempts=0; - while (p[0].page_end < p[1].page_start) { - uint32 probe; - uint32 start_offset, end_offset; - uint32 start_sample, end_sample; - - // copy these into local variables so we can tweak them - // if any are unknown - start_offset = p[0].page_end; - end_offset = p[1].after_previous_page_start; // an address known to seek to page p[1] - start_sample = p[0].last_decoded_sample; - end_sample = p[1].last_decoded_sample; - - // currently there is no such tweaking logic needed/possible? - if (start_sample == SAMPLE_unknown || end_sample == SAMPLE_unknown) - return error(f, VORBIS_seek_failed); - - // now we want to lerp between these for the target samples... - - // step 1: we need to bias towards the page start... - if (start_offset + 4000 < end_offset) - end_offset -= 4000; - - // now compute an interpolated search loc - probe = start_offset + (int) floor((float) (end_offset - start_offset) / (end_sample - start_sample) * (sample_number - start_sample)); - - // next we need to bias towards binary search... - // code is a little wonky to allow for full 32-bit unsigned values - if (attempts >= 4) { - uint32 probe2 = start_offset + ((end_offset - start_offset) >> 1); - if (attempts >= 8) - probe = probe2; - else if (probe < probe2) - probe = probe + ((probe2 - probe) >> 1); - else - probe = probe2 + ((probe - probe2) >> 1); - } - ++attempts; - - set_file_offset(f, probe); - if (!vorbis_find_page(f, NULL, NULL)) return error(f, VORBIS_seek_failed); - if (!vorbis_analyze_page(f, &q)) return error(f, VORBIS_seek_failed); - q.after_previous_page_start = probe; - - // it's possible we've just found the last page again - if (q.page_start == p[1].page_start) { - p[1] = q; - continue; - } - - if (sample_number < q.last_decoded_sample) - p[1] = q; - else - p[0] = q; - } - - if (p[0].last_decoded_sample <= sample_number && sample_number < p[1].last_decoded_sample) { - vorbis_seek_frame_from_page(f, p[1].page_start, p[0].last_decoded_sample, sample_number, fine); - return 0; - } - return error(f, VORBIS_seek_failed); - } -} - -int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) -{ - return vorbis_seek_base(f, sample_number, FALSE); -} - -int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) -{ - return vorbis_seek_base(f, sample_number, TRUE); -} - -void stb_vorbis_seek_start(stb_vorbis *f) -{ - if (IS_PUSH_MODE(f)) { error(f, VORBIS_invalid_api_mixing); return; } - set_file_offset(f, f->first_audio_page_offset); - f->previous_length = 0; - f->first_decode = TRUE; - f->next_seg = -1; - vorbis_pump_first_frame(f); -} - -unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) -{ - unsigned int restore_offset, previous_safe; - unsigned int end, last_page_loc; - - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - if (!f->total_samples) { - unsigned int last; - uint32 lo,hi; - char header[6]; - - // first, store the current decode position so we can restore it - restore_offset = stb_vorbis_get_file_offset(f); - - // now we want to seek back 64K from the end (the last page must - // be at most a little less than 64K, but let's allow a little slop) - if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset) - previous_safe = f->stream_len - 65536; - else - previous_safe = f->first_audio_page_offset; - - set_file_offset(f, previous_safe); - // previous_safe is now our candidate 'earliest known place that seeking - // to will lead to the final page' - - if (!vorbis_find_page(f, &end, &last)) { - // if we can't find a page, we're hosed! - f->error = VORBIS_cant_find_last_page; - f->total_samples = 0xffffffff; - goto done; - } - - // check if there are more pages - last_page_loc = stb_vorbis_get_file_offset(f); - - // stop when the last_page flag is set, not when we reach eof; - // this allows us to stop short of a 'file_section' end without - // explicitly checking the length of the section - while (!last) { - set_file_offset(f, end); - if (!vorbis_find_page(f, &end, &last)) { - // the last page we found didn't have the 'last page' flag - // set. whoops! - break; - } - previous_safe = last_page_loc+1; - last_page_loc = stb_vorbis_get_file_offset(f); - } - - set_file_offset(f, last_page_loc); - - // parse the header - getn(f, (unsigned char *)header, 6); - // extract the absolute granule position - lo = get32(f); - hi = get32(f); - if (lo == 0xffffffff && hi == 0xffffffff) { - f->error = VORBIS_cant_find_last_page; - f->total_samples = SAMPLE_unknown; - goto done; - } - if (hi) - lo = 0xfffffffe; // saturate - f->total_samples = lo; - - f->p_last.page_start = last_page_loc; - f->p_last.page_end = end; - f->p_last.last_decoded_sample = lo; - f->p_last.first_decoded_sample = SAMPLE_unknown; - f->p_last.after_previous_page_start = previous_safe; - - done: - set_file_offset(f, restore_offset); - } - return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; -} - -float stb_vorbis_stream_length_in_seconds(stb_vorbis *f) -{ - return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate; -} - - - -int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) -{ - int len, right,left,i; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - - if (!vorbis_decode_packet(f, &len, &left, &right)) { - f->channel_buffer_start = f->channel_buffer_end = 0; - return 0; - } - - len = vorbis_finish_frame(f, len, left, right); - for (i=0; i < f->channels; ++i) - f->outputs[i] = f->channel_buffers[i] + left; - - f->channel_buffer_start = left; - f->channel_buffer_end = left+len; - - if (channels) *channels = f->channels; - if (output) *output = f->outputs; - return len; -} - -#ifndef STB_VORBIS_NO_STDIO - -stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc, unsigned int length) -{ - stb_vorbis *f, p; - vorbis_init(&p, alloc); - p.f = file; - p.f_start = ftell(file); - p.stream_len = length; - p.close_on_free = close_on_free; - if (start_decoder(&p)) { - f = vorbis_alloc(&p); - if (f) { - *f = p; - vorbis_pump_first_frame(f); - return f; - } - } - if (error) *error = p.error; - vorbis_deinit(&p); - return NULL; -} - -stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc) -{ - unsigned int len, start; - start = ftell(file); - fseek(file, 0, SEEK_END); - len = ftell(file) - start; - fseek(file, start, SEEK_SET); - return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); -} - -stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorbis_alloc *alloc) -{ - FILE *f = fopen(filename, "rb"); - if (f) - return stb_vorbis_open_file(f, TRUE, error, alloc); - if (error) *error = VORBIS_file_open_failure; - return NULL; -} -#endif // STB_VORBIS_NO_STDIO - -stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, stb_vorbis_alloc *alloc) -{ - stb_vorbis *f, p; - if (data == NULL) return NULL; - vorbis_init(&p, alloc); - p.stream = (uint8 *) data; - p.stream_end = (uint8 *) data + len; - p.stream_start = (uint8 *) p.stream; - p.stream_len = len; - p.push_mode = FALSE; - if (start_decoder(&p)) { - f = vorbis_alloc(&p); - if (f) { - *f = p; - vorbis_pump_first_frame(f); - return f; - } - } - if (error) *error = p.error; - vorbis_deinit(&p); - return NULL; -} - -#ifndef STB_VORBIS_NO_INTEGER_CONVERSION -#define PLAYBACK_MONO 1 -#define PLAYBACK_LEFT 2 -#define PLAYBACK_RIGHT 4 - -#define L (PLAYBACK_LEFT | PLAYBACK_MONO) -#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO) -#define R (PLAYBACK_RIGHT | PLAYBACK_MONO) - -static int8 channel_position[7][6] = -{ - { 0 }, - { C }, - { L, R }, - { L, C, R }, - { L, R, L, R }, - { L, C, R, L, R }, - { L, C, R, L, R, C }, -}; - - -#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT - typedef union { - float f; - int i; - } float_conv; - typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4]; - #define FASTDEF(x) float_conv x - // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round - #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) - #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) - #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) - #define check_endianness() -#else - #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) - #define check_endianness() - #define FASTDEF(x) -#endif - -static void copy_samples(short *dest, float *src, int len) -{ - int i; - check_endianness(); - for (i=0; i < len; ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - dest[i] = v; - } -} - -static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) -{ - #define BUFFER_SIZE 32 - float buffer[BUFFER_SIZE]; - int i,j,o,n = BUFFER_SIZE; - check_endianness(); - for (o = 0; o < len; o += BUFFER_SIZE) { - memset(buffer, 0, sizeof(buffer)); - if (o + n > len) n = len - o; - for (j=0; j < num_c; ++j) { - if (channel_position[num_c][j] & mask) { - for (i=0; i < n; ++i) - buffer[i] += data[j][d_offset+o+i]; - } - } - for (i=0; i < n; ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - output[o+i] = v; - } - } -} - -static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) -{ - #define BUFFER_SIZE 32 - float buffer[BUFFER_SIZE]; - int i,j,o,n = BUFFER_SIZE >> 1; - // o is the offset in the source data - check_endianness(); - for (o = 0; o < len; o += BUFFER_SIZE >> 1) { - // o2 is the offset in the output data - int o2 = o << 1; - memset(buffer, 0, sizeof(buffer)); - if (o + n > len) n = len - o; - for (j=0; j < num_c; ++j) { - int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); - if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) { - for (i=0; i < n; ++i) { - buffer[i*2+0] += data[j][d_offset+o+i]; - buffer[i*2+1] += data[j][d_offset+o+i]; - } - } else if (m == PLAYBACK_LEFT) { - for (i=0; i < n; ++i) { - buffer[i*2+0] += data[j][d_offset+o+i]; - } - } else if (m == PLAYBACK_RIGHT) { - for (i=0; i < n; ++i) { - buffer[i*2+1] += data[j][d_offset+o+i]; - } - } - } - for (i=0; i < (n<<1); ++i) { - FASTDEF(temp); - int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - output[o2+i] = v; - } - } -} - -static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) -{ - int i; - if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { - static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; - for (i=0; i < buf_c; ++i) - compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples); - } else { - int limit = buf_c < data_c ? buf_c : data_c; - for (i=0; i < limit; ++i) - copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples); - for ( ; i < buf_c; ++i) - memset(buffer[i]+b_offset, 0, sizeof(short) * samples); - } -} - -int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples) -{ - float **output; - int len = stb_vorbis_get_frame_float(f, NULL, &output); - if (len > num_samples) len = num_samples; - if (len) - convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); - return len; -} - -static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len) -{ - int i; - check_endianness(); - if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { - assert(buf_c == 2); - for (i=0; i < buf_c; ++i) - compute_stereo_samples(buffer, data_c, data, d_offset, len); - } else { - int limit = buf_c < data_c ? buf_c : data_c; - int j; - for (j=0; j < len; ++j) { - for (i=0; i < limit; ++i) { - FASTDEF(temp); - float f = data[i][d_offset+j]; - int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15); - if ((unsigned int) (v + 32768) > 65535) - v = v < 0 ? -32768 : 32767; - *buffer++ = v; - } - for ( ; i < buf_c; ++i) - *buffer++ = 0; - } - } -} - -int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts) -{ - float **output; - int len; - if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts); - len = stb_vorbis_get_frame_float(f, NULL, &output); - if (len) { - if (len*num_c > num_shorts) len = num_shorts / num_c; - convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); - } - return len; -} - -int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts) -{ - float **outputs; - int len = num_shorts / channels; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < len) { - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - if (k) - convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k); - buffer += k*channels; - n += k; - f->channel_buffer_start += k; - if (n == len) break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; - } - return n; -} - -int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len) -{ - float **outputs; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < len) { - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - if (k) - convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); - n += k; - f->channel_buffer_start += k; - if (n == len) break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; - } - return n; -} - -#ifndef STB_VORBIS_NO_STDIO -int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output) -{ - int data_len, offset, total, limit, error; - short *data; - stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); - if (v == NULL) return -1; - limit = v->channels * 4096; - *channels = v->channels; - if (sample_rate) - *sample_rate = v->sample_rate; - offset = data_len = 0; - total = limit; - data = (short *) malloc(total * sizeof(*data)); - if (data == NULL) { - stb_vorbis_close(v); - return -2; - } - for (;;) { - int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); - if (n == 0) break; - data_len += n; - offset += n * v->channels; - if (offset + limit > total) { - short *data2; - total *= 2; - data2 = (short *) realloc(data, total * sizeof(*data)); - if (data2 == NULL) { - free(data); - stb_vorbis_close(v); - return -2; - } - data = data2; - } - } - *output = data; - stb_vorbis_close(v); - return data_len; -} -#endif // NO_STDIO - -int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output) -{ - int data_len, offset, total, limit, error; - short *data; - stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL); - if (v == NULL) return -1; - limit = v->channels * 4096; - *channels = v->channels; - if (sample_rate) - *sample_rate = v->sample_rate; - offset = data_len = 0; - total = limit; - data = (short *) malloc(total * sizeof(*data)); - if (data == NULL) { - stb_vorbis_close(v); - return -2; - } - for (;;) { - int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); - if (n == 0) break; - data_len += n; - offset += n * v->channels; - if (offset + limit > total) { - short *data2; - total *= 2; - data2 = (short *) realloc(data, total * sizeof(*data)); - if (data2 == NULL) { - free(data); - stb_vorbis_close(v); - return -2; - } - data = data2; - } - } - *output = data; - stb_vorbis_close(v); - return data_len; -} -#endif // STB_VORBIS_NO_INTEGER_CONVERSION - -int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats) -{ - float **outputs; - int len = num_floats / channels; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < len) { - int i,j; - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= len) k = len - n; - for (j=0; j < k; ++j) { - for (i=0; i < z; ++i) - *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j]; - for ( ; i < channels; ++i) - *buffer++ = 0; - } - n += k; - f->channel_buffer_start += k; - if (n == len) - break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) - break; - } - return n; -} - -int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples) -{ - float **outputs; - int n=0; - int z = f->channels; - if (z > channels) z = channels; - while (n < num_samples) { - int i; - int k = f->channel_buffer_end - f->channel_buffer_start; - if (n+k >= num_samples) k = num_samples - n; - if (k) { - for (i=0; i < z; ++i) - memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k); - for ( ; i < channels; ++i) - memset(buffer[i]+n, 0, sizeof(float) * k); - } - n += k; - f->channel_buffer_start += k; - if (n == num_samples) - break; - if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) - break; - } - return n; -} -#endif // STB_VORBIS_NO_PULLDATA_API - -/* Version history - 1.05 - 2015/04/19 - don't define __forceinline if it's redundant - 1.04 - 2014/08/27 - fix missing const-correct case in API - 1.03 - 2014/08/07 - Warning fixes - 1.02 - 2014/07/09 - Declare qsort compare function _cdecl on windows - 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float - 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in multichannel - (API change) report sample rate for decode-full-file funcs - 0.99996 - bracket #include for macintosh compilation by Laurent Gomila - 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem - 0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence - 0.99993 - remove assert that fired on legal files with empty tables - 0.99992 - rewind-to-start - 0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo - 0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++ - 0.9998 - add a full-decode function with a memory source - 0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition - 0.9996 - query length of vorbis stream in samples/seconds - 0.9995 - bugfix to another optimization that only happened in certain files - 0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors - 0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation - 0.9992 - performance improvement of IMDCT; now performs close to reference implementation - 0.9991 - performance improvement of IMDCT - 0.999 - (should have been 0.9990) performance improvement of IMDCT - 0.998 - no-CRT support from Casey Muratori - 0.997 - bugfixes for bugs found by Terje Mathisen - 0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen - 0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen - 0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen - 0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen - 0.992 - fixes for MinGW warning - 0.991 - turn fast-float-conversion on by default - 0.990 - fix push-mode seek recovery if you seek into the headers - 0.98b - fix to bad release of 0.98 - 0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode - 0.97 - builds under c++ (typecasting, don't use 'class' keyword) - 0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code - 0.95 - clamping code for 16-bit functions - 0.94 - not publically released - 0.93 - fixed all-zero-floor case (was decoding garbage) - 0.92 - fixed a memory leak - 0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION - 0.90 - first public release -*/ - -#endif // STB_VORBIS_HEADER_ONLY From 7b24469bf14510c3d8de32ac5f0cf0634d4d81a0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:33:49 -0700 Subject: [PATCH 074/522] update version / credits --- stb_tilemap_editor.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 9ba39e2..64480ba 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1,4 +1,4 @@ -// stb_tilemap_editor.h - v0.35 - Sean Barrett - http://nothings.org/stb +// stb_tilemap_editor.h - v0.36 - Sean Barrett - http://nothings.org/stb // placed in the public domain - not copyrighted - first released 2014-09 // // Embeddable tilemap editor for C/C++ @@ -275,6 +275,7 @@ // either approach allows cut&pasting between levels.) // // REVISION HISTORY +// 0.36 minor compiler support // 0.35 layername button changes // - layername buttons grow with the layer panel // - fix stbte_create_map being declared as stbte_create @@ -309,7 +310,7 @@ // Additional features: // Josh Huelsman // Bugfixes: -// [this could be you!] +// Ryan Whitworth // // LICENSE // From 264bc5725fa3f0a29829918aef979ebfc86dc2c4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:37:24 -0700 Subject: [PATCH 075/522] credits --- stb_truetype.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_truetype.h b/stb_truetype.h index 9392969..e41117c 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -39,6 +39,7 @@ // Omar Cornut // github:aloucks // Peter LaValle +// Sergey Popov // Giumo X. Clanjor // // Misc other: From d993ce7a5b197875a39af98fe3dff55892c2441d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:37:36 -0700 Subject: [PATCH 076/522] update readme --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e485d67..4a742ad 100644 --- a/README.md +++ b/README.md @@ -8,26 +8,26 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **stb_vorbis.c** | 1.06 | audio | 5441 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.06 | graphics | 6438 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_image.h** | 2.07 | graphics | 6502 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **stb_truetype.h** | 1.07 | graphics | 3220 | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 0.98 | graphics | 735 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.06 | graphics | 566 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **stb_textedit.h** | 1.6 | UI | 1290 | guts of a text editor for games etc implementing them from scratch -**stb_voxel_render.h** | 0.82 | 3D graphics | 3746 | Minecraft-esque voxel rendering "engine" with many more features +**stb_voxel_render.h** | 0.83 | 3D graphics | 3750 | Minecraft-esque voxel rendering "engine" with many more features **stb_dxt.h** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **stb_perlin.h** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) -**stb_easy_font.h** | 0.5 | 3D graphics | 226 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc -**stb_tilemap_editor.h** | 0.35 | game dev | 4120 | embeddable tilemap editor +**stb_easy_font.h** | 0.6 | 3D graphics | 232 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc +**stb_tilemap_editor.h** | 0.36 | game dev | 4127 | embeddable tilemap editor **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **stb_c_lexer.h** | 0.06 | parsing | 815 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**stb.h** | 2.24 | misc | 14093 | helper functions for C, mostly redundant in C++; basically author's personal stuff -**stb_leakcheck.h** | 0.2 | misc | 122 | quick-and-dirty malloc/free leak-checking +**stb.h** | 2.25 | misc | 14136 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46025 +Total lines of C code: 46151 FAQ From 2a1716cc8ff8b7f7a76eea162281e14f01c1b50c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:41:16 -0700 Subject: [PATCH 077/522] credits --- stb_image_write.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 7c350b7..6ffc3b7 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v0.99 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 no warranty implied; use at your own risk @@ -74,6 +74,7 @@ CREDITS: Tim Kelsey bugfixes: github:Chribba + Guillaume Chereau LICENSE @@ -720,6 +721,8 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 0.99 (2015-09-13) + warning fixes 0.98 (2015-04-08) added STBIW_MALLOC, STBIW_ASSERT etc 0.97 (2015-01-18) From 9bf98d619f0962d00ae3f47811b0764a2603247e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:41:30 -0700 Subject: [PATCH 078/522] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4a742ad..b996291 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **stb_vorbis.c** | 1.06 | audio | 5441 | decode ogg vorbis files from file/memory to float/16-bit signed output **stb_image.h** | 2.07 | graphics | 6502 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.07 | graphics | 3220 | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 0.98 | graphics | 735 | image writing to disk: PNG, TGA, BMP +**stb_truetype.h** | 1.07 | graphics | 3221 | parse, decode, and rasterize characters from truetype fonts +**stb_image_write.h** | 0.99 | graphics | 744 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.06 | graphics | 566 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ @@ -27,7 +27,7 @@ library | lastest version | category | LoC | description **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46151 +Total lines of C code: 46161 FAQ From a84daa614e119d27a4aebded8f451cd492f4f255 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:46:43 -0700 Subject: [PATCH 079/522] a few more stb_image_write fixes --- stb_image_write.h | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 6ffc3b7..4a667c8 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -75,6 +75,7 @@ CREDITS: bugfixes: github:Chribba Guillaume Chereau + github:jry2 LICENSE @@ -109,6 +110,11 @@ STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const #ifdef STB_IMAGE_WRITE_IMPLEMENTATION +#ifdef _WIN32 + #define _CRT_SECURE_NO_WARNINGS + #define _CRT_NONSTDC_NO_DEPRECATE +#endif + #include #include #include @@ -287,7 +293,7 @@ void stbiw__write_dump_data(FILE *f, int length, unsigned char *data) fwrite(data, length, 1, f); } -void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline) +void stbiw__write_hdr_scanline(FILE *f, int width, int ncomp, unsigned char *scratch, const float *scanline) { unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; unsigned char rgbe[4]; @@ -300,14 +306,14 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra /* skip RLE for images too small or large */ if (width < 8 || width >= 32768) { for (x=0; x < width; x++) { - switch (comp) { + switch (ncomp) { case 4: /* fallthrough */ - case 3: linear[2] = scanline[x*comp + 2]; - linear[1] = scanline[x*comp + 1]; - linear[0] = scanline[x*comp + 0]; + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; break; default: - linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; break; } stbiw__linear_to_rgbe(rgbe, linear); @@ -317,14 +323,14 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra int c,r; /* encode into scratch buffer */ for (x=0; x < width; x++) { - switch(comp) { + switch(ncomp) { case 4: /* fallthrough */ - case 3: linear[2] = scanline[x*comp + 2]; - linear[1] = scanline[x*comp + 1]; - linear[0] = scanline[x*comp + 0]; + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; break; default: - linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; break; } stbiw__linear_to_rgbe(rgbe, linear); @@ -562,8 +568,9 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l { // compute adler32 on input - unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552; - int j=0; + unsigned int k=0, s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; while (j < data_len) { for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; s1 %= 65521, s2 %= 65521; From 5bcce366386ff1e8faf0852083cc6c5147a93bd5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 06:58:45 -0700 Subject: [PATCH 080/522] rle tweaks, credits --- stb_image_write.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index dc0c793..5a906b5 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -62,6 +62,9 @@ USAGE: data, alpha (if provided) is discarded, and for monochrome data it is replicated across all three channels. + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + CREDITS: PNG/BMP/TGA @@ -72,6 +75,8 @@ CREDITS: Jean-Sebastien Guay misc enhancements: Tim Kelsey + TGA RLE + Alan Hickman bugfixes: github:Chribba Guillaume Chereau @@ -95,6 +100,7 @@ extern "C" { #define STBIWDEF static #else #define STBIWDEF extern +extern int stbi_write_tga_with_rle; #endif STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); @@ -147,7 +153,12 @@ STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; -static int stbi__write_tga_with_rle = 1; + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_tga_with_rle = 1; +#else +int stbi_write_tga_with_rle = 1; +#endif static void writefv(FILE *f, const char *fmt, va_list v) { @@ -270,7 +281,7 @@ STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 FILE *f; - if (!stbi__write_tga_with_rle) { + if (!stbi_write_tga_with_rle) { return outfile(filename, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); } @@ -810,7 +821,7 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const /* Revision history 0.99 (2015-09-13) - warning fixes + warning fixes; TGA rle support 0.98 (2015-04-08) added STBIW_MALLOC, STBIW_ASSERT etc 0.97 (2015-01-18) From 36574182c0e39469315583d151c3ad2b42c7ab92 Mon Sep 17 00:00:00 2001 From: Nathan Reed Date: Sun, 13 Sep 2015 11:00:46 -0700 Subject: [PATCH 081/522] Fix new VS2015 warnings in stb_image 2.07 - conversion from int to stbi_uc - unused parameter --- stb_image.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index b82de7b..207ff39 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5222,7 +5222,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int // Read the data. if (bitdepth == 16) { for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get16be(s) >> 8; + *p = (stbi_uc) (stbi__get16be(s) >> 8); } else { for (i = 0; i < pixelCount; i++, p += 4) *p = stbi__get8(s); @@ -5764,7 +5764,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i if (o == NULL) return NULL; if (prev_trans != -1) - g->pal[g->transparent][3] = prev_trans; + g->pal[g->transparent][3] = (stbi_uc) prev_trans; return o; } @@ -5795,6 +5795,8 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i return stbi__errpuc("unknown code", "Corrupt GIF"); } } + + STBI_NOTUSED(req_comp); } static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) From d5b8af12cbeeb9d7f4734ebfef8af93e0de74451 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 11:08:40 -0700 Subject: [PATCH 082/522] fix missing "defined" in #if defined(STBI_NO_foo); fix incorrect initialization of alpha channel for RGB PSD --- stb_image.h | 13 +++++++++---- tests/stb.dsp | 4 ++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index b82de7b..1140865 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.07 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.08 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -146,6 +146,7 @@ Latest revision history: + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) partial animated GIF support limited 16-bit PSD support minor bugs, code cleanup, and compiler warnings @@ -211,6 +212,7 @@ Phil Jordan Nathan Reed Michaelangel007@github + Nick Verigakis LICENSE @@ -1300,7 +1302,8 @@ static stbi__uint32 stbi__get32be(stbi__context *s) return (z << 16) + stbi__get16be(s); } -#if defined (STBI_NO_BMP) && (STBI_NO_TGA) && (STBI_NO_GIF) +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing #else static int stbi__get16le(stbi__context *s) { @@ -5214,10 +5217,11 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int stbi_uc *p; p = out + channel; - if (channel > channelCount) { + if (channel >= channelCount) { // Fill this channel with default data. + stbi_uc val = channel == 3 ? 255 : 0; for (i = 0; i < pixelCount; i++, p += 4) - *p = channel == 3 ? 255 : 0; + *p = val; } else { // Read the data. if (bitdepth == 16) { @@ -6355,6 +6359,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) fix compiler warnings partial animated GIF support limited 16-bit PSD support diff --git a/tests/stb.dsp b/tests/stb.dsp index 621f5a4..b4e1748 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -106,6 +106,10 @@ SOURCE=..\stb_dxt.h # End Source File # Begin Source File +SOURCE=..\stb_easy_font.h +# End Source File +# Begin Source File + SOURCE=..\stb_herringbone_wang_tile.h # End Source File # Begin Source File From 83d36fd28a2f25bbcbf887832d896203957f8b92 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 11:17:13 -0700 Subject: [PATCH 083/522] fix bug in handling rectangle with width or height of 0 --- stb_rect_pack.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index ac13df6..ac0fcf2 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.06 - public domain - rectangle packing +// stb_rect_pack.h - v0.07 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -28,10 +28,11 @@ // Minor features // Martins Mozeiko // Bugfixes / warning fixes -// [your name could be here] +// Jeremy Jaussaud // // Version history: // +// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort // 0.05: added STBRP_ASSERT to allow replacing assert // 0.04: fixed minor bug in STBRP_LARGE_RECTS support @@ -548,11 +549,16 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n for (i=0; i < num_rects; ++i) { stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); - if (fr.prev_link) { - rects[i].x = (stbrp_coord) fr.x; - rects[i].y = (stbrp_coord) fr.y; + + if (rects[i].w == 0 || rects[i].h == 0) { + rects[i].x = rects[i].y = 0; // empty rect needs no space } else { - rects[i].x = rects[i].y = STBRP__MAXVAL; + if (fr.prev_link) { + rects[i].x = (stbrp_coord) fr.x; + rects[i].y = (stbrp_coord) fr.y; + } else { + rects[i].x = rects[i].y = STBRP__MAXVAL; + } } } From 54b187972533fbe2bb6b2d350358fce4ef19add1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 11:23:33 -0700 Subject: [PATCH 084/522] document stbtt_Rasterize --- stb_truetype.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index e41117c..6453d34 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.07 - public domain +// stb_truetype.h - v1.08 - public domain // authored from 2009-2015 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -47,6 +47,7 @@ // // VERSION HISTORY // +// 1.08 (2015-09-13) document stbtt_Rasterize() // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); @@ -803,7 +804,16 @@ typedef struct unsigned char *pixels; } stbtt__bitmap; -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata); +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC ////////////////////////////////////////////////////////////////////////////// // From ff116a4fe85e68689fe492890f57efc7bf5622d1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 11:42:54 -0700 Subject: [PATCH 085/522] allow font ranges with first_char = 0; fix divide by 0 for exactly-vertical edges; fix possible divide by 0 for exactly-horizontal edges add documentation for stbtt_Rasterize; --- stb_truetype.h | 22 +++++++++++++--------- tests/test_truetype.c | 12 ++++++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 6453d34..a868596 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -41,13 +41,14 @@ // Peter LaValle // Sergey Popov // Giumo X. Clanjor +// Higor Euripedes // // Misc other: // Ryan Gordon // // VERSION HISTORY // -// 1.08 (2015-09-13) document stbtt_Rasterize() +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); @@ -1695,7 +1696,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i //STBTT_assert(e->y0 <= start_point); if (!z) return z; z->fdx = dxdy; - z->fdy = (1/dxdy); + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; z->fx = e->x0 + dxdy * (start_point - e->y0); z->fx -= off_x; z->direction = e->invert ? 1.0f : -1.0f; @@ -2098,11 +2099,13 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, // insert all edges that start before the bottom of this scanline while (e->y0 <= scan_y_bottom) { - stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - STBTT_assert(z->ey >= scan_y_top); - // insert at front - z->next = active; - active = z; + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + STBTT_assert(z->ey >= scan_y_top); + // insert at front + z->next = active; + active = z; + } ++e; } @@ -2845,7 +2848,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon ranges[i].v_oversample = (unsigned char) spc->v_oversample; for (j=0; j < ranges[i].num_chars; ++j) { int x0,y0,x1,y1; - int codepoint = ranges[i].first_unicode_codepoint_in_range ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * spc->h_oversample, @@ -2886,7 +2889,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt if (r->was_packed) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; int advance, lsb, x0,y0,x1,y1; - int codepoint = ranges[i].first_unicode_codepoint_in_range ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); stbrp_coord pad = (stbrp_coord) spc->padding; @@ -3189,6 +3192,7 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // FULL VERSION HISTORY // +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // allow PackFontRanges to pack and render in separate phases; // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); diff --git a/tests/test_truetype.c b/tests/test_truetype.c index 1ace8b2..4b78152 100644 --- a/tests/test_truetype.c +++ b/tests/test_truetype.c @@ -24,6 +24,7 @@ void debug(void) unsigned char temp_bitmap[BITMAP_H][BITMAP_W]; stbtt_bakedchar cdata[256*2]; // ASCII 32..126 is 95 glyphs stbtt_packedchar pdata[256*2]; + int main(int argc, char **argv) { stbtt_fontinfo font; @@ -35,6 +36,17 @@ int main(int argc, char **argv) // @TODO: why is minglui.ttc failing? fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/mingliu.ttc", "rb")); + //fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/x/DroidSansMono.ttf", "rb")); + { + static stbtt_pack_context pc; + static stbtt_packedchar cd[256]; + static unsigned char atlas[1024*1024]; + + stbtt_PackBegin(&pc, atlas, 1024,1024,1024,1,NULL); + stbtt_PackFontRange(&pc, ttf_buffer, 0, 32.0, 0, 256, cd); + stbtt_PackEnd(&pc); + } + #if 0 stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits! stbi_write_png("fonttest1.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0); From 4de75eb0cc129bbfd7fa29cbc7381476305523d9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 13:35:51 -0700 Subject: [PATCH 086/522] stb_textedit: better support for baseline at bottom stb_textedit: end-of-line handling places cursor before newline stb_truetype: avoid compiler warning due to local vars hiding local vars readme: add list of one-file libs --- stb_textedit.h | 25 ++++++++++++++++++------- stb_truetype.h | 24 ++++++++++++------------ tools/README.footer.md | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index b8309ff..6740b91 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// stb_textedit.h - v1.6 - public domain - Sean Barrett +// stb_textedit.h - v1.7 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -31,6 +31,7 @@ // // VERSION HISTORY // +// 1.7 (2015-09-13) change y range handling in case baseline is non-0 // 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove // 1.5 (2014-09-10) add support for secondary keys for OS X // 1.4 (2014-08-17) fix signed/unsigned warnings @@ -45,10 +46,14 @@ // ADDITIONAL CONTRIBUTORS // // Ulf Winklemann: move-by-word in 1.1 -// Scott Graham: mouse selection bugfix in 1.3 // Fabian Giesen: secondary key inputs in 1.5 // Martins Mozeiko: STB_TEXTEDIT_memmove // +// Bugfixes: +// Scott Graham +// Daniel Keller +// Omar Cornut +// // USAGE // // This file behaves differently depending on what symbols you define @@ -380,9 +385,6 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) float base_y = 0, prev_x; int i=0, k; - if (y < 0) - return 0; - r.x0 = r.x1 = 0; r.ymin = r.ymax = 0; r.num_chars = 0; @@ -393,6 +395,9 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) if (r.num_chars <= 0) return n; + if (i==0 && y < base_y + r.ymin) + return 0; + if (y < base_y + r.ymax) break; @@ -986,8 +991,11 @@ retry: stb_textedit_clamp(str, state); stb_textedit_move_to_first(state); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - state->cursor = find.first_char + find.length; + state->has_preferred_x = 0; + state->cursor = find.first_char + find.length; + if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE) + --state->cursor; break; } @@ -1012,8 +1020,11 @@ retry: stb_textedit_clamp(str, state); stb_textedit_prep_selection_at_cursor(state); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - state->cursor = state->select_end = find.first_char + find.length; state->has_preferred_x = 0; + state->cursor = find.first_char + find.length; + if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE) + --state->cursor; + state->select_end = state->cursor; break; } diff --git a/stb_truetype.h b/stb_truetype.h index a868596..00d22eb 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1919,7 +1919,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, float dx = e->fdx; float xb = x0 + dx; float x_top, x_bottom; - float y0,y1; + float sy0,sy1; float dy = e->fdy; STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); @@ -1928,17 +1928,17 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // line with y_top, but that may be off the line segment. if (e->sy > y_top) { x_top = x0 + dx * (e->sy - y_top); - y0 = e->sy; + sy0 = e->sy; } else { x_top = x0; - y0 = y_top; + sy0 = y_top; } if (e->ey < y_bottom) { x_bottom = x0 + dx * (e->ey - y_top); - y1 = e->ey; + sy1 = e->ey; } else { x_bottom = xb; - y1 = y_bottom; + sy1 = y_bottom; } if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { @@ -1948,7 +1948,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, float height; // simple case, only spans one pixel int x = (int) x_top; - height = y1 - y0; + height = sy1 - sy0; STBTT_assert(x >= 0 && x < len); scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; scanline_fill[x] += e->direction * height; // everything right of this pixel is filled @@ -1959,9 +1959,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, if (x_top > x_bottom) { // flip scanline vertically; signed area is the same float t; - y0 = y_bottom - (y0 - y_top); - y1 = y_bottom - (y1 - y_top); - t = y0, y0 = y1, y1 = t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; t = x_bottom, x_bottom = x_top, x_top = t; dx = -dx; dy = -dy; @@ -1975,7 +1975,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, sign = e->direction; // area of the rectangle covered from y0..y_crossing - area = sign * (y_crossing-y0); + area = sign * (y_crossing-sy0); // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); @@ -1988,9 +1988,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, STBTT_assert(fabs(area) <= 1.01f); - scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (y1-y_crossing); + scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); - scanline_fill[x2] += sign * (y1-y0); + scanline_fill[x2] += sign * (sy1-sy0); } } else { // if edge goes outside of box we're drawing, we require diff --git a/tools/README.footer.md b/tools/README.footer.md index aa07eeb..23c3336 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -70,7 +70,40 @@ too rare or if the size of implementation vs. apparent benefit is too low. #### Are there other single-file public-domain libraries out there? -Yes. I'll put a list here when people remind me what they are. +Yes. Here are some: + +- [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) +- [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) +- [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) +- [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) + +- [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) +- [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) + +- [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) +- [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) +- [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) + +- [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) +- [utest](https://github.com/evolutional/utest): unit testing (MIT license) + +There are some that have a source file and require a separate header file (which they may +not even supply). That's twice as many files, and we at nothings/stb cannot condone +this! But you might like them anyway: + +- [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) +- [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) +- [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write, uses miniz internally (BSD license) +- [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) +- [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) +- [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) +- [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) +- [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) + +There is also this XML library, but if you're using XML, shame on you: + +- [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) #### Do you have any advice on how to create my own single-file library? From 55eefc5739525a7a843faf9cf714060f9d29e530 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 14:51:49 -0700 Subject: [PATCH 087/522] add list of single-file libs --- tools/README.footer.md | 86 +++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/tools/README.footer.md b/tools/README.footer.md index 23c3336..d288c3b 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -8,6 +8,53 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. +#### Are there other single-file public-domain libraries out there? + +Yes. I'll even tell you about some. However, I haven't used most of these libraries +and can't comment on their quality. (If you use them and aren't their author, feel +free to tell me about their quality.) + +- [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) +- [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) +- [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) +- [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) + +- [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) +- [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) + +- [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) +- [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) +- [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) + +- [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) +- [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) +- [utest](https://github.com/evolutional/utest): unit testing (MIT license) +- [catch](https://github.com/philsquared/Catch): unit testing (Boost license) +- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) + +There are some that have a source file and require a separate header file (which they may +not even supply). That's twice as many files, and we at nothings/stb cannot condone +this! But you might like them anyway: + +- [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) +- [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) +- [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) +- [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) +- [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write, uses miniz internally (BSD license) +- [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) +- [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) +- [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) +- [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) +- [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) +- [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) +- [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) +- [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) + +There is also this XML library, but if you're using XML, shame on you: + +- [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) + #### If I wrap an stb library in a new library, does the new library have to be public domain? No. @@ -57,7 +104,7 @@ 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 semi-robust +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.c? @@ -68,43 +115,6 @@ 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. -#### Are there other single-file public-domain libraries out there? - -Yes. Here are some: - -- [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) -- [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) -- [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) -- [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - -- [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) -- [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) - -- [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) -- [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) -- [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - -- [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) -- [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- [utest](https://github.com/evolutional/utest): unit testing (MIT license) - -There are some that have a source file and require a separate header file (which they may -not even supply). That's twice as many files, and we at nothings/stb cannot condone -this! But you might like them anyway: - -- [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) -- [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write, uses miniz internally (BSD license) -- [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) -- [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) -- [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) -- [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) - -There is also this XML library, but if you're using XML, shame on you: - -- [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) - #### 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 From e847954d2742dcc243ef6aeb1fd02f1a6f38567a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 14:53:34 -0700 Subject: [PATCH 088/522] update readme --- README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b996291..f04985a 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **stb_vorbis.c** | 1.06 | audio | 5441 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.07 | graphics | 6502 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.07 | graphics | 3221 | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 0.99 | graphics | 744 | image writing to disk: PNG, TGA, BMP +**stb_image.h** | 2.08 | graphics | 6509 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_truetype.h** | 1.08 | graphics | 3235 | parse, decode, and rasterize characters from truetype fonts +**stb_image_write.h** | 0.99 | graphics | 843 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality -**stb_rect_pack.h** | 0.06 | graphics | 566 | simple 2D rectangle packer with decent quality +**stb_rect_pack.h** | 0.07 | graphics | 572 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**stb_textedit.h** | 1.6 | UI | 1290 | guts of a text editor for games etc implementing them from scratch +**stb_textedit.h** | 1.7 | UI | 1301 | guts of a text editor for games etc implementing them from scratch **stb_voxel_render.h** | 0.83 | 3D graphics | 3750 | Minecraft-esque voxel rendering "engine" with many more features **stb_dxt.h** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **stb_perlin.h** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) @@ -27,7 +27,7 @@ library | lastest version | category | LoC | description **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46161 +Total lines of C code: 46298 FAQ @@ -39,6 +39,53 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. +#### Are there other single-file public-domain libraries out there? + +Yes. I'll even tell you about some. However, I haven't used most of these libraries +and can't comment on their quality. (If you use them and aren't their author, feel +free to tell me about their quality.) + +- [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) +- [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) +- [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) +- [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) + +- [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) +- [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) + +- [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) +- [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) +- [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) + +- [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) +- [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) +- [utest](https://github.com/evolutional/utest): unit testing (MIT license) +- [catch](https://github.com/philsquared/Catch): unit testing (Boost license) +- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) + +There are some that have a source file and require a separate header file (which they may +not even supply). That's twice as many files, and we at nothings/stb cannot condone +this! But you might like them anyway: + +- [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) +- [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) +- [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) +- [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) +- [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write, uses miniz internally (BSD license) +- [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) +- [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) +- [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) +- [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) +- [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) +- [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) +- [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) +- [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) + +There is also this XML library, but if you're using XML, shame on you: + +- [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) + #### If I wrap an stb library in a new library, does the new library have to be public domain? No. @@ -88,7 +135,7 @@ 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 semi-robust +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.c? @@ -99,10 +146,6 @@ 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. -#### Are there other single-file public-domain libraries out there? - -Yes. I'll put a list here when people remind me what they are. - #### 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 From b74da797af656330628d359876959cbb5aa12b26 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 16:07:49 -0700 Subject: [PATCH 089/522] properly fix stb_rect_pack; tweak formatting of FAQ list --- stb_rect_pack.h | 4 ++-- tools/README.footer.md | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index ac0fcf2..e4cab80 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -32,6 +32,7 @@ // // Version history: // +// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort // 0.05: added STBRP_ASSERT to allow replacing assert @@ -548,11 +549,10 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); for (i=0; i < num_rects; ++i) { - stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); - if (rects[i].w == 0 || rects[i].h == 0) { rects[i].x = rects[i].y = 0; // empty rect needs no space } else { + stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); if (fr.prev_link) { rects[i].x = (stbrp_coord) fr.x; rects[i].y = (stbrp_coord) fr.y; diff --git a/tools/README.footer.md b/tools/README.footer.md index d288c3b..0e1f44f 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -18,25 +18,24 @@ free to tell me about their quality.) - [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) - [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) - [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - - [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) - - [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) - [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - - [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - [utest](https://github.com/evolutional/utest): unit testing (MIT license) - [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) +- [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone this! But you might like them anyway: +- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) +- [whereami](https://github.com/gpakosz/whereami): get path/filename of executable (WTFPL v2 license) - [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) - [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) - [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) From 8b7b845c4e8fa8955760e5f51661f9d9b24809bc Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 16:13:16 -0700 Subject: [PATCH 090/522] bump version number --- stb_rect_pack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index e4cab80..c61de89 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.07 - public domain - rectangle packing +// stb_rect_pack.h - v0.08 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. From a0d064edaed4b2bc7af0fcbfaa67c7ed105ef7c7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 16:13:57 -0700 Subject: [PATCH 091/522] update readme --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f04985a..d2c0b6f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ library | lastest version | category | LoC | description **stb_truetype.h** | 1.08 | graphics | 3235 | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 0.99 | graphics | 843 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality -**stb_rect_pack.h** | 0.07 | graphics | 572 | simple 2D rectangle packer with decent quality +**stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **stb_textedit.h** | 1.7 | UI | 1301 | guts of a text editor for games etc implementing them from scratch **stb_voxel_render.h** | 0.83 | 3D graphics | 3750 | Minecraft-esque voxel rendering "engine" with many more features @@ -49,25 +49,24 @@ free to tell me about their quality.) - [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) - [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) - [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - - [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) - - [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) - [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - - [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - [utest](https://github.com/evolutional/utest): unit testing (MIT license) - [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) +- [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone this! But you might like them anyway: +- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) +- [whereami](https://github.com/gpakosz/whereami): get path/filename of executable (WTFPL v2 license) - [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) - [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) - [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) From 43789d11d9c0ab310e32ad5c81907c6373f700b3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 16:54:35 -0700 Subject: [PATCH 092/522] add tigr to single-file libs FAQ --- README.md | 1 + tools/README.footer.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index d2c0b6f..23edeae 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ this! But you might like them anyway: - [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) - [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) +- [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) There is also this XML library, but if you're using XML, shame on you: diff --git a/tools/README.footer.md b/tools/README.footer.md index 0e1f44f..92b7884 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -49,6 +49,7 @@ this! But you might like them anyway: - [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) - [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) +- [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) There is also this XML library, but if you're using XML, shame on you: From 288ef363581f5ca2f1af99d8cb196b0a9aacd544 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 16:56:07 -0700 Subject: [PATCH 093/522] anchor for external links to list --- README.md | 2 +- tools/README.footer.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23edeae..d0f86cf 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. -#### Are there other single-file public-domain libraries out there? +#### Are there other single-file public-domain libraries out there? Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel diff --git a/tools/README.footer.md b/tools/README.footer.md index 92b7884..9467bc3 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -8,7 +8,7 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. -#### Are there other single-file public-domain libraries out there? +#### Are there other single-file public-domain libraries out there? Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel From b30a97930e22d808e6efd0fce8b385b73e176d5b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 17:00:20 -0700 Subject: [PATCH 094/522] include URL with anchor so other people can find it --- README.md | 3 +++ tools/README.footer.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index d0f86cf..590c00d 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,9 @@ There is also this XML library, but if you're using XML, shame on you: - [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +You can use (this URL)[https://github.com/nothings/stb#other_libs] to link directly to this list. + + #### If I wrap an stb library in a new library, does the new library have to be public domain? No. diff --git a/tools/README.footer.md b/tools/README.footer.md index 9467bc3..acad064 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -55,6 +55,9 @@ There is also this XML library, but if you're using XML, shame on you: - [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +You can use (this URL)[https://github.com/nothings/stb#other_libs] to link directly to this list. + + #### If I wrap an stb library in a new library, does the new library have to be public domain? No. From 2722cfc3a0e0c11d3a4f5a98f242f39f1af2ed8c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 17:01:26 -0700 Subject: [PATCH 095/522] fix last --- README.md | 2 +- tools/README.footer.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 590c00d..0275fac 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ There is also this XML library, but if you're using XML, shame on you: - [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) -You can use (this URL)[https://github.com/nothings/stb#other_libs] to link directly to this list. +You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. #### If I wrap an stb library in a new library, does the new library have to be public domain? diff --git a/tools/README.footer.md b/tools/README.footer.md index acad064..c5ad21e 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -55,7 +55,7 @@ There is also this XML library, but if you're using XML, shame on you: - [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) -You can use (this URL)[https://github.com/nothings/stb#other_libs] to link directly to this list. +You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. #### If I wrap an stb library in a new library, does the new library have to be public domain? From 054d340c8c6e459b5e42d12334799b59a6921864 Mon Sep 17 00:00:00 2001 From: James Hofmann Date: Sun, 13 Sep 2015 18:20:06 -0700 Subject: [PATCH 096/522] fix spelling of "Hofmann" Interesting factoid: my last name has four valid spellings. In Germany, the one I use is apparently the most common, while the other spellings are typical in the United States. --- stb_voxel_render.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 9a06a2b..29f6fb7 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -186,7 +186,7 @@ // Features Porting Bugfixes & Warnings // Sean Barrett github:r-leyh Jesus Fernandez // Miguel Lechon github:Arbeiterunfallversicherungsgesetz -// Thomas Frase James Hoffman +// Thomas Frase James Hofmann // // VERSION HISTORY // From 1fa899a101ce13a9b13256732f039dc432e8f111 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 13 Sep 2015 18:36:51 -0700 Subject: [PATCH 097/522] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 0275fac..5b18163 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,20 @@ free to tell me about their quality.) - [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) - [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) - [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) + +  + - [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) + +  + - [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) - [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) + +  + - [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) From a2291e3e5dc81c41b4a79991e96663f8e8bd335d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 02:32:03 -0700 Subject: [PATCH 098/522] update single-file-libs list --- README.md | 107 +++++++++++++++++++++++++++-------------- tools/README.footer.md | 105 +++++++++++++++++++++++++++------------- tools/README.header.md | 2 +- 3 files changed, 144 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 0275fac..e8db515 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ stb === -single-file public domain libraries for C/C++ +single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- @@ -39,61 +39,94 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. -#### Are there other single-file public-domain libraries out there? +#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality.) -- [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) -- [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) -- [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) -- [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) -- [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) -- [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) -- [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) -- [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) -- [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) -- [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- [utest](https://github.com/evolutional/utest): unit testing (MIT license) -- [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) +- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) +- **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) +- **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) +- **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) +- **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) +- **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) +- **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) + +Not public domain: + +- **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) +- **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) +- **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) +- **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) +- **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) +- **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) +- **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) +- **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) +- **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) +- **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone this! But you might like them anyway: -- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) -- [whereami](https://github.com/gpakosz/whereami): get path/filename of executable (WTFPL v2 license) -- [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) -- [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) -- [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write, uses miniz internally (BSD license) -- [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) -- [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) -- [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) -- [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) -- [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) -- [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) +- **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) +- **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) +- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* +- **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) +- **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) +- **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) +- **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) +- **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) +- **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) +- **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) +- **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) +- **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) +- **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) +- **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) +- **compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license) +- **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) +- **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* +- **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) +- **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) +- **misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib) +- **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) +- **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) There is also this XML library, but if you're using XML, shame on you: -- [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +- **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) + +*List FAQ* + +###### Can I link directly to this list? You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. +###### Why isn't library XXX which is made of 3 or more files on this list? + +I draw the line arbitrarily at 2 files at most. (Note that some libraries that appear to +be two files require a separate LICENSE file, which made me leave them out). Some of these +libraries are still easy to drop into your project and build, so you might still be ok with them. +But since people come to stb for single-file public domain libraries, I feel that starts +to get too far from what we do here. + +###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? + +Probably because I don't know about it, feel free to submit an issue. But I might not include +it for various other reasons, including subtleties of what is 'minimal other dependencies' and +subtleties about what is 'lightweight'. + +###### Why isn't sqllite's amalgamated build on this list? + +Come on. #### If I wrap an stb library in a new library, does the new library have to be public domain? No. -#### A lot of these libraries seem redundant to existing open source libraries. Are they better somehow? +#### 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 @@ -101,6 +134,10 @@ 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, diff --git a/tools/README.footer.md b/tools/README.footer.md index c5ad21e..540d4da 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -8,61 +8,94 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. -#### Are there other single-file public-domain libraries out there? +#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality.) -- [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) -- [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) -- [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) -- [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) -- [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) -- [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) -- [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) -- [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) -- [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) -- [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- [utest](https://github.com/evolutional/utest): unit testing (MIT license) -- [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) +- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) +- **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) +- **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) +- **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) +- **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) +- **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) +- **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) + +Not public domain: + +- **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) +- **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) +- **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) +- **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) +- **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) +- **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) +- **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) +- **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) +- **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) +- **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone this! But you might like them anyway: -- [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): C++ flexible assertions in C++ (WTFPL v2 license) -- [whereami](https://github.com/gpakosz/whereami): get path/filename of executable (WTFPL v2 license) -- [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) -- [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) -- [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write, uses miniz internally (BSD license) -- [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) -- [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) -- [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) -- [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) -- [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) -- [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) +- **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) +- **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) +- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* +- **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) +- **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) +- **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) +- **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) +- **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) +- **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) +- **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) +- **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) +- **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) +- **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) +- **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) +- **compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license) +- **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) +- **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* +- **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) +- **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) +- **misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib) +- **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) +- **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) There is also this XML library, but if you're using XML, shame on you: -- [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +- **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) + +*List FAQ* + +###### Can I link directly to this list? You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. +###### Why isn't library XXX which is made of 3 or more files on this list? + +I draw the line arbitrarily at 2 files at most. (Note that some libraries that appear to +be two files require a separate LICENSE file, which made me leave them out). Some of these +libraries are still easy to drop into your project and build, so you might still be ok with them. +But since people come to stb for single-file public domain libraries, I feel that starts +to get too far from what we do here. + +###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? + +Probably because I don't know about it, feel free to submit an issue. But I might not include +it for various other reasons, including subtleties of what is 'minimal other dependencies' and +subtleties about what is 'lightweight'. + +###### Why isn't sqllite's amalgamated build on this list? + +Come on. #### If I wrap an stb library in a new library, does the new library have to be public domain? No. -#### A lot of these libraries seem redundant to existing open source libraries. Are they better somehow? +#### 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 @@ -70,6 +103,10 @@ 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, diff --git a/tools/README.header.md b/tools/README.header.md index f30e631..71e765b 100644 --- a/tools/README.header.md +++ b/tools/README.header.md @@ -1,7 +1,7 @@ stb === -single-file public domain libraries for C/C++ +single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- From 996f0b0a6b1067edd16e7afe7b9c6fa69e4c348b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 02:35:31 -0700 Subject: [PATCH 099/522] fix spelling of SQLite --- tools/README.footer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/README.footer.md b/tools/README.footer.md index 540d4da..7909991 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -87,7 +87,7 @@ Probably because I don't know about it, feel free to submit an issue. But I migh it for various other reasons, including subtleties of what is 'minimal other dependencies' and subtleties about what is 'lightweight'. -###### Why isn't sqllite's amalgamated build on this list? +###### Why isn't SQLite's amalgamated build on this list? Come on. From 99c7e64b6274b6a223f4e25846a9bb8d9a836206 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 02:35:47 -0700 Subject: [PATCH 100/522] rebuild README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8db515..78c8f55 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ Probably because I don't know about it, feel free to submit an issue. But I migh it for various other reasons, including subtleties of what is 'minimal other dependencies' and subtleties about what is 'lightweight'. -###### Why isn't sqllite's amalgamated build on this list? +###### Why isn't SQLite's amalgamated build on this list? Come on. From c2978ae79f73030b27475e57538a1d9af25d70cc Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 02:36:57 -0700 Subject: [PATCH 101/522] move anchor to *beginning* of question so links look better --- README.md | 2 +- tools/README.footer.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 78c8f55..359cf51 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. -#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? +#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel diff --git a/tools/README.footer.md b/tools/README.footer.md index 7909991..80378ed 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -8,7 +8,7 @@ These libraries are in the public domain (or the equivalent where that is not possible). You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution. -#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? +#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel From 955bd174a2796dd41461b57a52704c470c21acb2 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 04:53:31 -0700 Subject: [PATCH 102/522] update list --- tools/README.footer.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/README.footer.md b/tools/README.footer.md index 80378ed..f6292c4 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -31,6 +31,7 @@ Not public domain: - **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) +- **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) From 78fe0bfc2495e4fad2ae4a1fe4f1792f662ef09a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 05:40:12 -0700 Subject: [PATCH 103/522] handle fopen() failing --- stb_image_write.h | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 0deaf3b..a5a0553 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -197,10 +197,11 @@ static int stbi__stdio_write(void *user, void *data, int size) return (int) fwrite(data,1,size,(FILE*) user); } -static void stbi__start_write_file(stbi__write_context *s, const char *filename) +static int stbi__start_write_file(stbi__write_context *s, const char *filename) { FILE *f = fopen(filename, "wb"); stbi__start_write_callbacks(s, &stbi__stdio_write, (void *) f); + return f != NULL; } static void stbi__end_write_file(stbi__write_context *s) @@ -353,12 +354,13 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) { - int r; stbi__write_context s; - stbi__start_write_file(&s,filename); - r = stbi_write_bmp_core(&s, x, y, comp, data); - stbi__end_write_file(&s); - return r; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; } #endif //!STBI_WRITE_NO_STDIO @@ -440,12 +442,13 @@ int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, i #ifndef STBI_WRITE_NO_STDIO int stbi_write_tga_to_file(char const *filename, int x, int y, int comp, const void *data) { - int r; stbi__write_context s; - stbi__start_write_file(&s,filename); - r = stbi_write_tga_core(&s, x, y, comp, (void *) data); - stbi__end_write_file(&s); - return r; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; } #endif @@ -609,12 +612,13 @@ int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, i int stbi_write_hdr_to_file(char const *filename, int x, int y, int comp, const float *data) { - int r; stbi__write_context s; - stbi__start_write_file(&s,filename); - r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); - stbi__end_write_file(&s); - return r; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; } #endif // STBI_WRITE_NO_STDIO From b4477803cb9a2038fb9f4fc65b50d553395544c7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 05:48:24 -0700 Subject: [PATCH 104/522] fix public function names; fix internal names to be namspaced properly; --- stb_image_write.h | 52 ++++++++++++++++++++++++---------------------- tests/image_test.c | 11 +++++++++- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index a5a0553..7e6cd8f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v0.99 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.00 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 no warranty implied; use at your own risk @@ -89,7 +89,7 @@ CREDITS: Tim Kelsey TGA RLE Alan Hickman - file IO callback + initial file IO callback implementation Emmanuel Julien bugfixes: github:Chribba @@ -220,7 +220,7 @@ static int stbi_write_tga_with_rle = 1; int stbi_write_tga_with_rle = 1; #endif -static void writefv(stbi__write_context *s, const char *fmt, va_list v) +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) { while (*fmt) { switch (*fmt++) { @@ -249,22 +249,22 @@ static void writefv(stbi__write_context *s, const char *fmt, va_list v) } } -static void writef(stbi__write_context *s, const char *fmt, ...) +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) { va_list v; va_start(v, fmt); - writefv(s, fmt, v); + stbiw__writefv(s, fmt, v); va_end(v); } -static void write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) { unsigned char arr[3]; arr[0] = a, arr[1] = b, arr[2] = c; s->func(s->context, arr, 3); } -static void write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) { unsigned char bg[3] = { 255, 0, 255}, px[3]; int k; @@ -278,7 +278,7 @@ static void write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write break; case 2: if (expand_mono) - write3(s, d[0], d[0], d[0]); // monochrome bmp + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp else s->func(s->context, d, 1); // monochrome TGA break; @@ -287,19 +287,19 @@ static void write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write // composite against pink background for (k = 0; k < 3; ++k) px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; - write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); break; } /* FALLTHROUGH */ case 3: - write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); break; } if (write_alpha > 0) s->func(s->context, &d[comp - 1], 1); } -static void write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) { stbiw_uint32 zero = 0; int i,j, j_end; @@ -315,30 +315,30 @@ static void write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, i for (; j != j_end; j += vdir) { for (i=0; i < x; ++i) { unsigned char *d = (unsigned char *) data + (j*x+i)*comp; - write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); } s->func(s->context, &zero, scanline_pad); } } -static int outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) { if (y < 0 || x < 0) { return 0; } else { va_list v; va_start(v, fmt); - writefv(s, fmt, v); + stbiw__writefv(s, fmt, v); va_end(v); - write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); return 1; } } -STBIWDEF int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) { int pad = (-x*3) & 3; - return outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, "11 4 22 4" "4 44 22 444444", 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header @@ -364,7 +364,7 @@ STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const } #endif //!STBI_WRITE_NO_STDIO -STBIWDEF int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) { int has_alpha = (comp == 2 || comp == 4); int colorbytes = has_alpha ? comp-1 : comp; @@ -374,12 +374,12 @@ STBIWDEF int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, return 0; if (!stbi_write_tga_with_rle) { - return outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); } else { int i,j,k; - writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); for (j = y - 1; j >= 0; --j) { unsigned char *row = (unsigned char *) data + j * x * comp; @@ -419,12 +419,12 @@ STBIWDEF int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, unsigned char header = (unsigned char) (len - 1); s->func(s->context, &header, 1); for (k = 0; k < len; ++k) { - write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); } } else { unsigned char header = (unsigned char) (len - 129); s->func(s->context, &header, 1); - write_pixel(s, -1, comp, has_alpha, 0, begin); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); } } } @@ -440,7 +440,7 @@ int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, i } #ifndef STBI_WRITE_NO_STDIO -int stbi_write_tga_to_file(char const *filename, int x, int y, int comp, const void *data) +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) { stbi__write_context s; if (stbi__start_write_file(&s,filename)) { @@ -581,7 +581,7 @@ void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, uns } } -STBIWDEF int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) { if (y <= 0 || x <= 0 || data == NULL) return 0; @@ -610,7 +610,7 @@ int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, i return stbi_write_hdr_core(&s, x, y, comp, (float *) data); } -int stbi_write_hdr_to_file(char const *filename, int x, int y, int comp, const float *data) +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { stbi__write_context s; if (stbi__start_write_file(&s,filename)) { @@ -965,6 +965,8 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.00 (2015-09-14) + installable file IO function 0.99 (2015-09-13) warning fixes; TGA rle support 0.98 (2015-04-08) diff --git a/tests/image_test.c b/tests/image_test.c index bb395bc..59b2a76 100644 --- a/tests/image_test.c +++ b/tests/image_test.c @@ -53,12 +53,19 @@ void test_ycbcr(void) float hdr_data[200][200][3]; +void dummy(void *context, void *data, int len) +{ + static char dummy[1024]; + if (len > 1024) len = 1024; + memcpy(dummy, data, len); +} + int main(int argc, char **argv) { int w,h; //test_ycbcr(); - #if 0 + #if 1 // test hdr asserts for (h=0; h < 100; h += 2) for (w=0; w < 200; ++w) @@ -88,6 +95,8 @@ int main(int argc, char **argv) char fname[512]; stb_splitpath(fname, argv[i], STB_FILE); stbi_write_png(stb_sprintf("output/%s.png", fname), w, h, 4, data, w*4); + stbi_write_bmp(stb_sprintf("output/%s.bmp", fname), w, h, 4, data); + stbi_write_tga(stb_sprintf("output/%s.tga", fname), w, h, 4, data); free(data); } else printf("FAILED 4\n"); From 93b2b829963f637e9c90218da5e501d71c9a255b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 05:57:42 -0700 Subject: [PATCH 105/522] get rid of unused return value from write callback --- stb_image_write.h | 13 ++++++++----- tests/image_test.c | 5 ++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 7e6cd8f..38d3835 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,5 +1,5 @@ /* stb_image_write - v1.00 - public domain - http://nothings.org/stb/stb_image_write.h - writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk Before #including, @@ -44,6 +44,9 @@ USAGE: int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + where the callback is: + void stbi_write_func(void *context, void *data, int size); + You can define STBI_WRITE_NO_STDIO to disable the file variant of these functions, so the library will not use stdio.h at all. However, this will also disable HDR writing, because it requires stdio for formatted output. @@ -125,7 +128,7 @@ STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); #endif -typedef int stbi_write_func(void *context, void *data, int size); +typedef void stbi_write_func(void *context, void *data, int size); STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); @@ -192,15 +195,15 @@ static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func #ifndef STBI_WRITE_NO_STDIO -static int stbi__stdio_write(void *user, void *data, int size) +static void stbi__stdio_write(void *context, void *data, int size) { - return (int) fwrite(data,1,size,(FILE*) user); + fwrite(data,1,size,(FILE*) context); } static int stbi__start_write_file(stbi__write_context *s, const char *filename) { FILE *f = fopen(filename, "wb"); - stbi__start_write_callbacks(s, &stbi__stdio_write, (void *) f); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); return f != NULL; } diff --git a/tests/image_test.c b/tests/image_test.c index 59b2a76..9bb1832 100644 --- a/tests/image_test.c +++ b/tests/image_test.c @@ -53,7 +53,7 @@ void test_ycbcr(void) float hdr_data[200][200][3]; -void dummy(void *context, void *data, int len) +void dummy_write(void *context, void *data, int len) { static char dummy[1024]; if (len > 1024) len = 1024; @@ -97,6 +97,9 @@ int main(int argc, char **argv) stbi_write_png(stb_sprintf("output/%s.png", fname), w, h, 4, data, w*4); stbi_write_bmp(stb_sprintf("output/%s.bmp", fname), w, h, 4, data); stbi_write_tga(stb_sprintf("output/%s.tga", fname), w, h, 4, data); + stbi_write_png_to_func(dummy_write,0, w, h, 4, data, w*4); + stbi_write_bmp_to_func(dummy_write,0, w, h, 4, data); + stbi_write_tga_to_func(dummy_write,0, w, h, 4, data); free(data); } else printf("FAILED 4\n"); From ac7daffc276b6845f203f2adecf48a1e01cba909 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 05:58:09 -0700 Subject: [PATCH 106/522] update readme --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 359cf51..731da55 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ library | lastest version | category | LoC | description **stb_vorbis.c** | 1.06 | audio | 5441 | decode ogg vorbis files from file/memory to float/16-bit signed output **stb_image.h** | 2.08 | graphics | 6509 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **stb_truetype.h** | 1.08 | graphics | 3235 | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 0.99 | graphics | 843 | image writing to disk: PNG, TGA, BMP +**stb_image_write.h** | 1.00 | graphics | 993 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ @@ -27,7 +27,7 @@ library | lastest version | category | LoC | description **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46298 +Total lines of C code: 46448 FAQ @@ -62,6 +62,7 @@ Not public domain: - **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) +- **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) From 5378a965369b5870dff58b11e187688f83623a8c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 14 Sep 2015 07:07:20 -0700 Subject: [PATCH 107/522] clarify that olick's GIF also does animated --- README.md | 2 +- tools/README.footer.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 731da55..29c4e78 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Yes. I'll even tell you about some. However, I haven't used most of these librar and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality.) -- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) +- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) - **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) - **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) - **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) diff --git a/tools/README.footer.md b/tools/README.footer.md index f6292c4..914bf83 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -14,7 +14,7 @@ Yes. I'll even tell you about some. However, I haven't used most of these librar and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality.) -- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): tiny GIF writer (public domain) +- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) - **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) - **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) - **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) From 412e1ecc1620fd842b0d3ade2238c8918f5fb373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Sj=C3=B6strand?= Date: Tue, 15 Sep 2015 19:17:42 +0200 Subject: [PATCH 108/522] compile fix for MinGW --- stb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb.h b/stb.h index d8aaf37..2e98e9d 100644 --- a/stb.h +++ b/stb.h @@ -206,7 +206,7 @@ CREDITS #endif #endif -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW32__) #define _CRT_SECURE_NO_WARNINGS #define _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NON_CONFORMING_SWPRINTFS From b372a1f86c7cf11a9b0023c06a51b90037781c70 Mon Sep 17 00:00:00 2001 From: Sergio Gonzalez Date: Mon, 21 Sep 2015 12:18:18 -0500 Subject: [PATCH 109/522] Avoid macro redefinition in Win32 --- stb_image_write.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 38d3835..b963604 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -98,12 +98,12 @@ CREDITS: github:Chribba Guillaume Chereau github:jry2 - + LICENSE This software is in the public domain. Where that dedication is not recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. +distribute, and modify this file as you see fit. */ @@ -144,8 +144,12 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, #ifdef STB_IMAGE_WRITE_IMPLEMENTATION #ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NONSTDC_NO_DEPRECATE + #endif #endif #ifndef STBI_WRITE_NO_STDIO From 34d6c2ca873b51428d12804fb0305ce4cf0e3583 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 23 Sep 2015 05:01:16 -0700 Subject: [PATCH 110/522] update tinyexr's list position --- README.md | 2 +- tools/README.footer.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29c4e78..d64c7af 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ free to tell me about their quality.) Not public domain: +- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* - **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) @@ -74,7 +75,6 @@ this! But you might like them anyway: - **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) - **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* - **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) - **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) - **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) diff --git a/tools/README.footer.md b/tools/README.footer.md index 914bf83..7f63591 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -25,6 +25,7 @@ free to tell me about their quality.) Not public domain: +- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* - **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) @@ -43,7 +44,6 @@ this! But you might like them anyway: - **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) - **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* - **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) - **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) - **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) From 232927699c692be310af8252e64c43a73fcd0c17 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 23 Sep 2015 05:03:26 -0700 Subject: [PATCH 111/522] Vita warning fix --- stb_truetype.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 00d22eb..bf546c3 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.08 - public domain +// stb_truetype.h - v1.09 - public domain // authored from 2009-2015 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -42,12 +42,14 @@ // Sergey Popov // Giumo X. Clanjor // Higor Euripedes +// Thomas Fields // // Misc other: // Ryan Gordon // // VERSION HISTORY // +// 1.09 (????-??-??) warning fix // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; @@ -1556,7 +1558,7 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { - int x0,y0,x1,y1; + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { // e.g. space character if (ix0) *ix0 = 0; From 007c850b485823cd66439133f9a79ad295464198 Mon Sep 17 00:00:00 2001 From: Rasmus Christian Pedersen Date: Fri, 25 Sep 2015 19:46:27 +0200 Subject: [PATCH 112/522] nobug: removed unused variable 'k' --- stb_image_write.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 38d3835..ecc285f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -795,7 +795,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l { // compute adler32 on input - unsigned int k=0, s1=1, s2=0; + unsigned int s1=1, s2=0; int blocklen = (int) (data_len % 5552); j=0; while (j < data_len) { From 6998a8e064eeac13bbce69bda25c2fea8a7ccfbf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 26 Sep 2015 11:51:23 -0700 Subject: [PATCH 113/522] add gb_string.h --- README.md | 1 + tools/README.footer.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index d64c7af..9b33168 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ free to tell me about their quality.) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) +- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C Not public domain: diff --git a/tools/README.footer.md b/tools/README.footer.md index 7f63591..81eed5a 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -22,6 +22,7 @@ free to tell me about their quality.) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) +- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C Not public domain: From 616633b557a792c1059883e6041e83e63b7898d0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 26 Sep 2015 12:03:09 -0700 Subject: [PATCH 114/522] italicize most recent others' libs --- tools/README.footer.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/tools/README.footer.md b/tools/README.footer.md index 81eed5a..90526d8 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -12,7 +12,7 @@ to do anything else, although I appreciate attribution. Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel -free to tell me about their quality.) +free to tell me about their quality.) _Newest additions are in italics._ - **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) - **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) @@ -22,7 +22,7 @@ free to tell me about their quality.) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C +- _**misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C_ Not public domain: @@ -30,14 +30,14 @@ Not public domain: - **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) +- _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) +- _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) +- _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone @@ -45,23 +45,23 @@ this! But you might like them anyway: - **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) - **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) +- _**3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib)_ - **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) -- **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) -- **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) +- _**2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain)_ +- _**geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain)_ - **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) +- _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) - **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) - **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- **compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license) +- _**compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license)_ - **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- **misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib) +- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) @@ -85,9 +85,10 @@ to get too far from what we do here. ###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? -Probably because I don't know about it, feel free to submit an issue. But I might not include -it for various other reasons, including subtleties of what is 'minimal other dependencies' and -subtleties about what is 'lightweight'. +Probably because I don't know about it, feel free to submit an issue, email, or tweet it at +me (it can be your own library or somebody else's). But I might not include it for various +other reasons, including subtleties of what is 'minimal other dependencies' and subtleties +about what is 'lightweight'. ###### Why isn't SQLite's amalgamated build on this list? From 3eb363c193c9ebe88e3c554caa1d3004ae668fc9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 26 Sep 2015 12:03:24 -0700 Subject: [PATCH 115/522] italicize more recent others' libs --- README.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9b33168..97f9320 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ to do anything else, although I appreciate attribution. Yes. I'll even tell you about some. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel -free to tell me about their quality.) +free to tell me about their quality.) _Newest additions are in italics._ - **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) - **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) @@ -53,7 +53,7 @@ free to tell me about their quality.) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C +- _**misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C_ Not public domain: @@ -61,14 +61,14 @@ Not public domain: - **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) +- _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) +- _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) +- _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone @@ -76,23 +76,23 @@ this! But you might like them anyway: - **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) - **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) +- _**3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib)_ - **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) -- **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) -- **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) +- _**2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain)_ +- _**geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain)_ - **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) +- _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) - **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) - **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- **compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license) +- _**compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license)_ - **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- **misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib) +- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) @@ -116,9 +116,10 @@ to get too far from what we do here. ###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? -Probably because I don't know about it, feel free to submit an issue. But I might not include -it for various other reasons, including subtleties of what is 'minimal other dependencies' and -subtleties about what is 'lightweight'. +Probably because I don't know about it, feel free to submit an issue, email, or tweet it at +me (it can be your own library or somebody else's). But I might not include it for various +other reasons, including subtleties of what is 'minimal other dependencies' and subtleties +about what is 'lightweight'. ###### Why isn't SQLite's amalgamated build on this list? From 60e3ecac85065955d5cd1fc1038e762fe78375e6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 26 Sep 2015 12:14:37 -0700 Subject: [PATCH 116/522] added ImGui to other_libs --- README.md | 6 ++++++ tools/README.footer.md | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/README.md b/README.md index 97f9320..62b7e03 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,12 @@ There is also this XML library, but if you're using XML, shame on you: - **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +There are some libraries that are just _so_ awesome that even though they use more +than two files we're going to give them special dispensation to appear in their own +little list here. If you're a crazy purist, be warned, but otherwise, enjoy! + +- _**user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license)_ + *List FAQ* ###### Can I link directly to this list? diff --git a/tools/README.footer.md b/tools/README.footer.md index 90526d8..c355c54 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -69,6 +69,12 @@ There is also this XML library, but if you're using XML, shame on you: - **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +There are some libraries that are just _so_ awesome that even though they use more +than two files we're going to give them special dispensation to appear in their own +little list here. If you're a crazy purist, be warned, but otherwise, enjoy! + +- _**user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license)_ + *List FAQ* ###### Can I link directly to this list? From b1160eb7e9df9e639551e6004affdd9a84b54a0e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:09:25 -0700 Subject: [PATCH 117/522] update other_libs --- README.md | 13 ++++++++++--- tools/README.footer.md | 11 +++++++++-- tools/README.list | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 62b7e03..e11a0df 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ library | lastest version | category | LoC | description **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**stb_textedit.h** | 1.7 | UI | 1301 | guts of a text editor for games etc implementing them from scratch +**stb_textedit.h** | 1.7 | user interface | 1301 | guts of a text editor for games etc implementing them from scratch **stb_voxel_render.h** | 0.83 | 3D graphics | 3750 | Minecraft-esque voxel rendering "engine" with many more features **stb_dxt.h** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **stb_perlin.h** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) @@ -64,8 +64,10 @@ Not public domain: - _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) +- _**geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license)_ - _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) +- _**parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license)_ - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ @@ -83,6 +85,7 @@ this! But you might like them anyway: - **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) +- _**network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2)_ - _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) - **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) @@ -92,13 +95,17 @@ this! But you might like them anyway: - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib)_ +- _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ +- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ +- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license) - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) +- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) -There is also this XML library, but if you're using XML, shame on you: +There is also these XML libraries, but if you're using XML, shame on you: - **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) There are some libraries that are just _so_ awesome that even though they use more than two files we're going to give them special dispensation to appear in their own diff --git a/tools/README.footer.md b/tools/README.footer.md index c355c54..a417215 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -33,8 +33,10 @@ Not public domain: - _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) +- _**geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license)_ - _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) +- _**parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license)_ - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ @@ -52,6 +54,7 @@ this! But you might like them anyway: - **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) +- _**network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2)_ - _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) - **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) @@ -61,13 +64,17 @@ this! But you might like them anyway: - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib)_ +- _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ +- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ +- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license) - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) +- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) -There is also this XML library, but if you're using XML, shame on you: +There is also these XML libraries, but if you're using XML, shame on you: - **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) There are some libraries that are just _so_ awesome that even though they use more than two files we're going to give them special dispensation to appear in their own diff --git a/tools/README.list b/tools/README.list index 8cf1f5f..5ad58a1 100644 --- a/tools/README.list +++ b/tools/README.list @@ -5,7 +5,7 @@ stb_image_write.h | graphics | image writing to disk: PNG, TGA stb_image_resize.h | graphics | resize images larger/smaller with good quality stb_rect_pack.h | graphics | simple 2D rectangle packer with decent quality stretchy_buffer.h | utility | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -stb_textedit.h | UI | guts of a text editor for games etc implementing them from scratch +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) From 37a493ae21b7dec3c339ac0a4d73c1d0db7158c7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:11:02 -0700 Subject: [PATCH 118/522] fix typo --- tools/README.footer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/README.footer.md b/tools/README.footer.md index a417215..82cdf8e 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -66,7 +66,7 @@ this! But you might like them anyway: - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) - _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ - _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ -- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license) +- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) From 6464d059ab09e012a4e7f00fcbbbb91212d08d9c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:11:09 -0700 Subject: [PATCH 119/522] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e11a0df..373a76a 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ this! But you might like them anyway: - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) - _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ - _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ -- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license) +- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) From 847fb2c230859aa91eae47bba3b6fbb86fe91f84 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:13:09 -0700 Subject: [PATCH 120/522] put other_libs list in its own file --- docs/other_libs.md | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 docs/other_libs.md diff --git a/docs/other_libs.md b/docs/other_libs.md new file mode 100644 index 0000000..ff21519 --- /dev/null +++ b/docs/other_libs.md @@ -0,0 +1,95 @@ +#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? + +Yes. I'll even tell you about some. However, I haven't used most of these libraries +and can't comment on their quality. (If you use them and aren't their author, feel +free to tell me about their quality.) _Newest additions are in italics._ + +- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) +- **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) +- **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) +- **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) +- **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) +- **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) +- **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) +- _**misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C_ + +Not public domain: + +- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* +- **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) +- **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) +- **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) +- _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ +- **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) +- **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) +- _**geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license)_ +- _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ +- **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) +- _**parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license)_ +- **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) +- **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) +- _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ + +There are some that have a source file and require a separate header file (which they may +not even supply). That's twice as many files, and we at nothings/stb cannot condone +this! But you might like them anyway: + +- **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) +- **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) +- _**3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib)_ +- **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) +- _**2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain)_ +- _**geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain)_ +- **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) +- **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) +- **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) +- _**network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2)_ +- _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ +- **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) +- **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) +- **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) +- _**compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license)_ +- **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) +- **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* +- **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) +- **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) +- _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ +- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ +- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ +- **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) +- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ +- **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) + +There is also these XML libraries, but if you're using XML, shame on you: + +- **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) +- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) + +There are some libraries that are just _so_ awesome that even though they use more +than two files we're going to give them special dispensation to appear in their own +little list here. If you're a crazy purist, be warned, but otherwise, enjoy! + +- _**user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license)_ + +*List FAQ* + +###### Can I link directly to this list? + +You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. + +###### Why isn't library XXX which is made of 3 or more files on this list? + +I draw the line arbitrarily at 2 files at most. (Note that some libraries that appear to +be two files require a separate LICENSE file, which made me leave them out). Some of these +libraries are still easy to drop into your project and build, so you might still be ok with them. +But since people come to stb for single-file public domain libraries, I feel that starts +to get too far from what we do here. + +###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? + +Probably because I don't know about it, feel free to submit a pull request, issue, email, or tweet it at +me (it can be your own library or somebody else's). But I might not include it for various +other reasons, including subtleties of what is 'minimal other dependencies' and subtleties +about what is 'lightweight'. + From 4b587a409ab26b0e471c021863e5dd82ad101b97 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:14:48 -0700 Subject: [PATCH 121/522] Update other_libs.md --- docs/other_libs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index ff21519..a34c541 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -1,6 +1,6 @@ -#### Are there other single-file public-domain/open source libraries with minimal dependencies out there? +# Other single-file public-domain/open source libraries with minimal dependencies -Yes. I'll even tell you about some. However, I haven't used most of these libraries +People have told me about quite a few of these. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality.) _Newest additions are in italics._ @@ -72,13 +72,13 @@ little list here. If you're a crazy purist, be warned, but otherwise, enjoy! - _**user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license)_ -*List FAQ* +## *List FAQ* -###### Can I link directly to this list? +### Can I link directly to this list? -You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. +Yes, you can just use this page. If you want a shorter, more readable link, you can use [this URL](https://github.com/nothings/stb#other_libs) to link to the FAQ question that links to this page. -###### Why isn't library XXX which is made of 3 or more files on this list? +### Why isn't library XXX which is made of 3 or more files on this list? I draw the line arbitrarily at 2 files at most. (Note that some libraries that appear to be two files require a separate LICENSE file, which made me leave them out). Some of these @@ -86,7 +86,7 @@ libraries are still easy to drop into your project and build, so you might still But since people come to stb for single-file public domain libraries, I feel that starts to get too far from what we do here. -###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? +### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? Probably because I don't know about it, feel free to submit a pull request, issue, email, or tweet it at me (it can be your own library or somebody else's). But I might not include it for various From f6d172d92be7db105184419f80ec25be7b14616a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:15:32 -0700 Subject: [PATCH 122/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index a34c541..a4cf3d9 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -64,7 +64,7 @@ this! But you might like them anyway: There is also these XML libraries, but if you're using XML, shame on you: - **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) -- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) +- _**parsing** [pugixml](http://pugixml.org/): XML (MIT license)_ There are some libraries that are just _so_ awesome that even though they use more than two files we're going to give them special dispensation to appear in their own From 2bd2e571a22db8a3c48f5b4314d0d95f18a1f3cb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:16:13 -0700 Subject: [PATCH 123/522] Update other_libs.md --- docs/other_libs.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index a4cf3d9..e8e69fb 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -93,3 +93,7 @@ me (it can be your own library or somebody else's). But I might not include it f other reasons, including subtleties of what is 'minimal other dependencies' and subtleties about what is 'lightweight'. +### Why isn't SQLite's amalgamated build on this list? + +Come on. + From 8d0ae2d39ffa973230bc33ee4c35d221f046e42b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:16:33 -0700 Subject: [PATCH 124/522] move other_libs list to its own file --- README.md | 97 +----------------------------------------- tools/README.footer.md | 97 +----------------------------------------- 2 files changed, 2 insertions(+), 192 deletions(-) diff --git a/README.md b/README.md index 373a76a..0fb310e 100644 --- a/README.md +++ b/README.md @@ -41,102 +41,7 @@ to do anything else, although I appreciate attribution. #### Are there other single-file public-domain/open source libraries with minimal dependencies out there? -Yes. I'll even tell you about some. However, I haven't used most of these libraries -and can't comment on their quality. (If you use them and aren't their author, feel -free to tell me about their quality.) _Newest additions are in italics._ - -- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) -- **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) -- **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) -- **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) -- **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) -- **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) -- **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) -- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- _**misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C_ - -Not public domain: - -- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* -- **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) -- **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) -- **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ -- **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) -- **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- _**geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license)_ -- _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ -- **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) -- _**parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license)_ -- **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) -- **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ - -There are some that have a source file and require a separate header file (which they may -not even supply). That's twice as many files, and we at nothings/stb cannot condone -this! But you might like them anyway: - -- **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) -- **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- _**3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib)_ -- **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) -- _**2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain)_ -- _**geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain)_ -- **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) -- **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) -- **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- _**network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2)_ -- _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ -- **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) -- **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) -- **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- _**compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license)_ -- **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) -- **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* -- **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ -- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ -- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ -- **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) -- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ -- **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) - -There is also these XML libraries, but if you're using XML, shame on you: - -- **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) -- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) - -There are some libraries that are just _so_ awesome that even though they use more -than two files we're going to give them special dispensation to appear in their own -little list here. If you're a crazy purist, be warned, but otherwise, enjoy! - -- _**user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license)_ - -*List FAQ* - -###### Can I link directly to this list? - -You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. - -###### Why isn't library XXX which is made of 3 or more files on this list? - -I draw the line arbitrarily at 2 files at most. (Note that some libraries that appear to -be two files require a separate LICENSE file, which made me leave them out). Some of these -libraries are still easy to drop into your project and build, so you might still be ok with them. -But since people come to stb for single-file public domain libraries, I feel that starts -to get too far from what we do here. - -###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? - -Probably because I don't know about it, feel free to submit an issue, email, or tweet it at -me (it can be your own library or somebody else's). But I might not include it for various -other reasons, including subtleties of what is 'minimal other dependencies' and subtleties -about what is 'lightweight'. - -###### Why isn't SQLite's amalgamated build on this list? - -Come on. +[Yes.](https://github.com/nothings/stb/blob/master/docs/other_libs.md) #### If I wrap an stb library in a new library, does the new library have to be public domain? diff --git a/tools/README.footer.md b/tools/README.footer.md index 82cdf8e..e910267 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -10,102 +10,7 @@ to do anything else, although I appreciate attribution. #### Are there other single-file public-domain/open source libraries with minimal dependencies out there? -Yes. I'll even tell you about some. However, I haven't used most of these libraries -and can't comment on their quality. (If you use them and aren't their author, feel -free to tell me about their quality.) _Newest additions are in italics._ - -- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) -- **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) -- **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) -- **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) -- **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) -- **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) -- **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) -- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- _**misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C_ - -Not public domain: - -- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* -- **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) -- **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) -- **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ -- **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) -- **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- _**geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license)_ -- _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ -- **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) -- _**parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license)_ -- **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) -- **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ - -There are some that have a source file and require a separate header file (which they may -not even supply). That's twice as many files, and we at nothings/stb cannot condone -this! But you might like them anyway: - -- **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) -- **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- _**3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib)_ -- **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) -- _**2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain)_ -- _**geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain)_ -- **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) -- **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) -- **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- _**network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2)_ -- _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ -- **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) -- **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) -- **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- _**compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license)_ -- **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) -- **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* -- **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ -- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ -- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ -- **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) -- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ -- **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) - -There is also these XML libraries, but if you're using XML, shame on you: - -- **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) -- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) - -There are some libraries that are just _so_ awesome that even though they use more -than two files we're going to give them special dispensation to appear in their own -little list here. If you're a crazy purist, be warned, but otherwise, enjoy! - -- _**user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license)_ - -*List FAQ* - -###### Can I link directly to this list? - -You can use [this URL](https://github.com/nothings/stb#other_libs) to link directly to this list. - -###### Why isn't library XXX which is made of 3 or more files on this list? - -I draw the line arbitrarily at 2 files at most. (Note that some libraries that appear to -be two files require a separate LICENSE file, which made me leave them out). Some of these -libraries are still easy to drop into your project and build, so you might still be ok with them. -But since people come to stb for single-file public domain libraries, I feel that starts -to get too far from what we do here. - -###### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? - -Probably because I don't know about it, feel free to submit an issue, email, or tweet it at -me (it can be your own library or somebody else's). But I might not include it for various -other reasons, including subtleties of what is 'minimal other dependencies' and subtleties -about what is 'lightweight'. - -###### Why isn't SQLite's amalgamated build on this list? - -Come on. +[Yes.](https://github.com/nothings/stb/blob/master/docs/other_libs.md) #### If I wrap an stb library in a new library, does the new library have to be public domain? From cd9c6d7b436f643ac612bd3bc18025226974fc47 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:21:39 -0700 Subject: [PATCH 125/522] Update other_libs.md --- docs/other_libs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index e8e69fb..dd7b48e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -1,5 +1,7 @@ # Other single-file public-domain/open source libraries with minimal dependencies +In addition to all of [my libraries](https://github.com/nothings/stb), there are other, similar libraries. + People have told me about quite a few of these. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality.) _Newest additions are in italics._ From bbdb4f65efad46b47be8ddfd8f7cf198beb46d0c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:23:56 -0700 Subject: [PATCH 126/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index dd7b48e..a42086a 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -60,7 +60,7 @@ this! But you might like them anyway: - _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ - _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) -- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ +- _**misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) There is also these XML libraries, but if you're using XML, shame on you: From dc92c6c4c455e6c32222309e52978a55071c9c1c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 08:30:16 -0700 Subject: [PATCH 127/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index a42086a..a41e8ce 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -27,6 +27,7 @@ Not public domain: - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - _**geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license)_ - _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ +- _**mulithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license)_ - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - _**parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license)_ - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) From bdcc1535d6b5e2c8386f5126d267ab2bfeb9c8cb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 27 Sep 2015 11:04:06 -0700 Subject: [PATCH 128/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index a41e8ce..221fcc5 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -60,6 +60,7 @@ this! But you might like them anyway: - _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ - _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ - _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ +- _**misc** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - _**misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) From cc3bb7c45828e6db4d441e68f6af02f1d60d6109 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Oct 2015 09:43:27 -0700 Subject: [PATCH 129/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 221fcc5..017c449 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -63,6 +63,7 @@ this! But you might like them anyway: - _**misc** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - _**misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ +- _**misc** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license) - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) There is also these XML libraries, but if you're using XML, shame on you: From 0b79b3bfe1cf790ef783e1b9df4a8a9dd58fb91e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Oct 2015 09:43:46 -0700 Subject: [PATCH 130/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 017c449..f3f0690 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -63,7 +63,7 @@ this! But you might like them anyway: - _**misc** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain)_ - **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - _**misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ -- _**misc** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license) +- _**misc** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) There is also these XML libraries, but if you're using XML, shame on you: From 3e404042c5b1f02bd64d3430a5b79434aa95584a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 7 Oct 2015 21:53:40 -0700 Subject: [PATCH 131/522] other_libs: added TweetNaCl --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index f3f0690..a360b57 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -48,6 +48,7 @@ this! But you might like them anyway: - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) - _**network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2)_ +- _**crypto** [TweetNaCl](http://tweetnacl.cr.yp.to/software.html): high-quality tiny cryptography library (public domain)_ - _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) - **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) From 6a9cdd1c83630f4f27af8e0c6b8b6ba427354975 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 9 Oct 2015 02:03:44 -0700 Subject: [PATCH 132/522] other_libs: add a few libraries --- docs/other_libs.md | 49 ++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index a360b57..53dc747 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -12,9 +12,9 @@ free to tell me about their quality.) _Newest additions are in italics._ - **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) - **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) -- **misc** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- _**misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C_ +- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C Not public domain: @@ -22,17 +22,17 @@ Not public domain: - **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) - **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- _**2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license)_ +- **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- _**geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license)_ -- _**audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license)_ -- _**mulithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license)_ +- **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) +- **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) +- **mulithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) -- _**parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license)_ +- **parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license) - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- _**tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license)_ +- **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone @@ -40,43 +40,46 @@ this! But you might like them anyway: - **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) - **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- _**3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib)_ +- **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) - **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) -- _**2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain)_ -- _**geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain)_ +- **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) +- **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) - **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- _**network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2)_ +- **network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2) - _**crypto** [TweetNaCl](http://tweetnacl.cr.yp.to/software.html): high-quality tiny cryptography library (public domain)_ -- _**AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license)_ +- **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) - **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) - **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- _**compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license)_ +- **compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license) - **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) -- _**parsing** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license)_ -- _**misc** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license)_ -- _**misc** [klib](http://attractivechaos.github.io/klib/) many 2-file libs: hash, sort, b-tree, etc (MIT license)_ -- _**misc** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain)_ -- **misc** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) -- _**misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license)_ -- _**misc** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license)_ +- **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) +- **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license) +- **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) +- _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-file libs: generic hash, list, etc (BSD license)_ +- _**data structures** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license)_ +- **data structures**; **algorithms** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain) +- **files & filenames** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) +- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license) +- _**misc** [stmr](https://github.com/wooorm/stmr.c): extract English word stems (MIT license)_ +- _**misc** [levenshtein](https://github.com/wooorm/levenshtein.c): compute edit distance between two strings (MIT license)_ - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) There is also these XML libraries, but if you're using XML, shame on you: - **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) -- _**parsing** [pugixml](http://pugixml.org/): XML (MIT license)_ +- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) There are some libraries that are just _so_ awesome that even though they use more than two files we're going to give them special dispensation to appear in their own little list here. If you're a crazy purist, be warned, but otherwise, enjoy! -- _**user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license)_ +- **user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license) ## *List FAQ* From ff085b88f49935a43aec1828f7e64e371b7fa980 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 9 Oct 2015 02:11:28 -0700 Subject: [PATCH 133/522] Update other_libs.md --- docs/other_libs.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 53dc747..2fb1bf6 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -61,7 +61,7 @@ this! But you might like them anyway: - **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license) - **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) -- _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-file libs: generic hash, list, etc (BSD license)_ +- _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license)_ - _**data structures** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license)_ - **data structures**; **algorithms** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain) - **files & filenames** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) @@ -79,7 +79,11 @@ There are some libraries that are just _so_ awesome that even though they use mo than two files we're going to give them special dispensation to appear in their own little list here. If you're a crazy purist, be warned, but otherwise, enjoy! -- **user interface** [ImGui](https://github.com/ocornut/imgui) an immediate-mode GUI ("imgui") named "ImGui" (MIT license) +- **user interface** [ImGui](https://github.com/ocornut/imgui): an immediate-mode GUI ("imgui") named "ImGui" (MIT license) + +Also you might be interested in other related, but different lists: + +- [clib](https://github.com/clibs/clib/wiki/Packages): list of (mostly) small single C functions (licenses not listed) ## *List FAQ* From c4082cfb890946a0c37df6b4c97f57b52042969e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 9 Oct 2015 15:31:50 -0700 Subject: [PATCH 134/522] Update other_libs.md --- docs/other_libs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2fb1bf6..10325a1 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -26,8 +26,9 @@ Not public domain: - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) +- _**network** [wby](https://github.com/vurtun/wby): lightweight webserver, fork of webby (BSD license)_ - **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) -- **mulithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) +- **multithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license) - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) From 35fcd0817fe192941a8840365bb783314b435667 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Fri, 9 Oct 2015 20:46:59 -0500 Subject: [PATCH 135/522] stb_vorbis.c: Silence -pedantic warning. --- stb_vorbis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 98e96fb..dded3c6 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -367,7 +367,7 @@ enum STBVorbisError VORBIS_invalid_first_page, VORBIS_bad_packet_type, VORBIS_cant_find_last_page, - VORBIS_seek_failed, + VORBIS_seek_failed }; @@ -1576,7 +1576,7 @@ enum { VORBIS_packet_id = 1, VORBIS_packet_comment = 3, - VORBIS_packet_setup = 5, + VORBIS_packet_setup = 5 }; static int codebook_decode_scalar_raw(vorb *f, Codebook *c) From 385927fb4b8a06d72402fb3971acea1d67142ec4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 15 Oct 2015 17:59:40 -0700 Subject: [PATCH 136/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 10325a1..0e0433b 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -31,6 +31,7 @@ Not public domain: - **multithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license) +- _**parsing** [zange](https://github.com/vurtun/zange): JSON parser (MIT license)_ - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) From f1d401845ff937207772b10917713abfac25e911 Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Sat, 17 Oct 2015 17:33:00 +0200 Subject: [PATCH 137/522] Fix race condition in static crc_table If calling stbi_write_png concurrently the static array crc_table would be shared between threads causing data-races. --- stb_image_write.h | 76 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 38d3835..6f440c1 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -817,14 +817,76 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l unsigned int stbiw__crc32(unsigned char *buffer, int len) { - static unsigned int crc_table[256]; + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + unsigned int crc = ~0u; - int i,j; - if (crc_table[1] == 0) - for(i=0; i < 256; i++) - for (crc_table[i]=i, j=0; j < 8; ++j) - crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0); - for (i=0; i < len; ++i) + for (int i=0; i < len; ++i) crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; return ~crc; } From 22dd50f25653944863898601ee66bdef121fd51a Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Tue, 20 Oct 2015 22:03:50 +0200 Subject: [PATCH 138/522] Fix documentation error --- stb_image_write.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 38d3835..6014164 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -34,7 +34,7 @@ USAGE: int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); - int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); There are also four equivalent functions that use an arbitrary write function. You are expected to open/close your file-equivalent before and after calling these: From b95858a2f772c83421f02ef2e3352d737f78178e Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Tue, 20 Oct 2015 23:22:27 +0200 Subject: [PATCH 139/522] Add bitmask to unsigned char casts to fix MSVC runtime checks --- stb_image_write.h | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 38d3835..2036c83 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -180,6 +180,8 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, #define STBIW_ASSERT(x) assert(x) #endif +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + typedef struct { stbi_write_func *func; @@ -228,21 +230,21 @@ static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) while (*fmt) { switch (*fmt++) { case ' ': break; - case '1': { unsigned char x = (unsigned char) va_arg(v, int); + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); s->func(s->context,&x,1); break; } case '2': { int x = va_arg(v,int); unsigned char b[2]; - b[0] = (unsigned char) x; - b[1] = (unsigned char) (x>>8); + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); s->func(s->context,b,2); break; } case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4]; - b[0]=(unsigned char)x; - b[1]=(unsigned char)(x>>8); - b[2]=(unsigned char)(x>>16); - b[3]=(unsigned char)(x>>24); + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); s->func(s->context,b,4); break; } default: @@ -419,13 +421,13 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v } if (diff) { - unsigned char header = (unsigned char) (len - 1); + unsigned char header = STBIW_UCHAR(len - 1); s->func(s->context, &header, 1); for (k = 0; k < len; ++k) { stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); } } else { - unsigned char header = (unsigned char) (len - 129); + unsigned char header = STBIW_UCHAR(len - 129); s->func(s->context, &header, 1); stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); } @@ -481,7 +483,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) { - unsigned char lengthbyte = (unsigned char) (length+128); + unsigned char lengthbyte = STBIW_UCHAR(length+128); STBIW_ASSERT(length+128 <= 255); s->func(s->context, &lengthbyte, 1); s->func(s->context, &databyte, 1); @@ -489,7 +491,7 @@ void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char dat void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) { - unsigned char lengthbyte = (unsigned char )(length & 0xff); + unsigned char lengthbyte = STBIW_UCHAR(length); STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code s->func(s->context, &lengthbyte, 1); s->func(s->context, data, length); @@ -660,7 +662,7 @@ static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) { while (*bitcount >= 8) { - stbiw__sbpush(data, (unsigned char) *bitbuffer); + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); *bitbuffer >>= 8; *bitcount -= 8; } @@ -804,10 +806,10 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l j += blocklen; blocklen = 5552; } - stbiw__sbpush(out, (unsigned char) (s2 >> 8)); - stbiw__sbpush(out, (unsigned char) s2); - stbiw__sbpush(out, (unsigned char) (s1 >> 8)); - stbiw__sbpush(out, (unsigned char) s1); + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); } *out_len = stbiw__sbn(out); // make returned pointer freeable @@ -829,7 +831,7 @@ unsigned int stbiw__crc32(unsigned char *buffer, int len) return ~crc; } -#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4) +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) @@ -842,9 +844,9 @@ static void stbiw__wpcrc(unsigned char **data, int len) static unsigned char stbiw__paeth(int a, int b, int c) { int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); - if (pa <= pb && pa <= pc) return (unsigned char) a; - if (pb <= pc) return (unsigned char) b; - return (unsigned char) c; + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); } unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) @@ -917,7 +919,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in stbiw__wp32(o, x); stbiw__wp32(o, y); *o++ = 8; - *o++ = (unsigned char) ctype[n]; + *o++ = STBIW_UCHAR(ctype[n]); *o++ = 0; *o++ = 0; *o++ = 0; From 8cea0090b2fcb193b32d9c33a5ee0155f23dfa64 Mon Sep 17 00:00:00 2001 From: Filip Wasil Date: Thu, 29 Oct 2015 16:09:21 +0100 Subject: [PATCH 140/522] Removie implicit cast to float When compiling with more restrictive compiler options such casting from double to float will cause a warning. Ex. GCC -Wdouble-promotion Signed-off-by: Filip Wasil --- stb_image_write.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 38d3835..6c241ea 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -467,7 +467,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) int exponent; float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); - if (maxcomp < 1e-32) { + if (maxcomp < 1e-32f) { rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; } else { float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; From 06ae60645efc713362fef70ef6d9c69516ddd425 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 31 Oct 2015 11:17:02 -0700 Subject: [PATCH 141/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0e0433b..2931064 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -35,6 +35,7 @@ Not public domain: - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) +- _**misc** [lualite](https://github.com/janezz55/lualite/): generate lua bindings in C++ (MIT license)_ There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone From ba406835155888c048da2c41eeb909fe204123cf Mon Sep 17 00:00:00 2001 From: Michael Sartain Date: Fri, 30 Oct 2015 19:10:03 -0700 Subject: [PATCH 142/522] readdir_raw was skipping all dirnames starting with dots. Only skip . and .. --- stb.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/stb.h b/stb.h index d8aaf37..c57079e 100644 --- a/stb.h +++ b/stb.h @@ -5863,6 +5863,13 @@ void stb_readdir_free(char **files) stb_arr_free(f2); } +static int isdotdirname(char *name) +{ + if (name[0] == '.') + return (name[1] == '.') ? !name[2] : !name[1]; + return 0; +} + STB_EXTERN int stb_wildmatchi(char *expr, char *candidate); static char **readdir_raw(char *dir, int return_subdirs, char *mask) { @@ -5931,7 +5938,7 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) #endif if (is_subdir == return_subdirs) { - if (!is_subdir || name[0] != '.') { + if (!is_subdir || !isdotdirname(name)) { if (!mask || stb_wildmatchi(mask, name)) { char buffer[512],*p=buffer; sprintf(buffer, "%s%s", with_slash, name); From 8d9302ab05294b5fecc4bd445651521b8cc7fc38 Mon Sep 17 00:00:00 2001 From: Michael Sartain Date: Sun, 1 Nov 2015 17:47:11 -0800 Subject: [PATCH 143/522] readdir_raw buffer overrun fixes. - Add stb_vsnprintf, stb_snprintf functions. - stb snprintf routines should return -1 on buffer truncation on all platforms. - Add stb_strscpy string copy function which should behave the same as Linux kernel strscpy. - Bump readdir_raw buffer sizes up to 4k, add checks for path truncations. - Use d_type to check for directory instead of opendir/closedir. This should be faster and fix recursive symlnk death. --- stb.h | 85 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/stb.h b/stb.h index c57079e..187619d 100644 --- a/stb.h +++ b/stb.h @@ -714,20 +714,41 @@ STB_EXTERN char * stb_sstrdup(char *s); STB_EXTERN void stbprint(const char *fmt, ...); STB_EXTERN char *stb_sprintf(const char *fmt, ...); STB_EXTERN char *stb_mprintf(const char *fmt, ...); +STB_EXTERN int stb_snprintf(char *s, size_t n, const char *fmt, ...); +STB_EXTERN int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v); #ifdef STB_DEFINE +int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v) +{ + int res; + #ifdef _WIN32 + // Could use "_vsnprintf_s(s, n, _TRUNCATE, fmt, v)" ? + res = _vsnprintf(s,n,fmt,v); + #else + res = vsnprintf(s,n,fmt,v); + #endif + if (n) s[n-1] = 0; + // Unix returns length output would require, Windows returns negative when truncated. + return (res >= n || res < 0) ? -1 : res; +} + +int stb_snprintf(char *s, size_t n, const char *fmt, ...) +{ + int res; + va_list v; + va_start(v,fmt); + res = stb_vsnprintf(s, n, fmt, v); + va_end(v); + return res; +} + char *stb_sprintf(const char *fmt, ...) { static char buffer[1024]; va_list v; va_start(v,fmt); - #ifdef _WIN32 - _vsnprintf(buffer, 1024, fmt, v); - #else - vsnprintf(buffer, 1024, fmt, v); - #endif + stb_vsnprintf(buffer,1024,fmt,v); va_end(v); - buffer[1023] = 0; return buffer; } @@ -736,13 +757,8 @@ char *stb_mprintf(const char *fmt, ...) static char buffer[1024]; va_list v; va_start(v,fmt); - #ifdef _WIN32 - _vsnprintf(buffer, 1024, fmt, v); - #else - vsnprintf(buffer, 1024, fmt, v); - #endif + stb_vsnprintf(buffer,1024,fmt,v); va_end(v); - buffer[1023] = 0; return strdup(buffer); } @@ -842,9 +858,8 @@ void stbprint(const char *fmt, ...) va_list v; va_start(v,fmt); - res = _vsnprintf(buffer, sizeof(buffer), fmt, v); + res = stb_vsnprintf(buffer, sizeof(buffer), fmt, v); va_end(v); - buffer[sizeof(buffer)-1] = 0; if (res < 0) { tbuf = (char *) malloc(16384); @@ -1765,6 +1780,7 @@ STB_EXTERN char * stb_strichr(char *s, char t); STB_EXTERN char * stb_stristr(char *s, char *t); STB_EXTERN int stb_prefix_count(char *s, char *t); STB_EXTERN char * stb_plural(int n); // "s" or "" +STB_EXTERN size_t stb_strscpy(char *d, const char *s, size_t n); STB_EXTERN char **stb_tokens(char *src, char *delimit, int *count); STB_EXTERN char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out); @@ -1779,6 +1795,17 @@ STB_EXTERN char **stb_tokens_quoted(char *src, char *delimit, int *count); #ifdef STB_DEFINE +size_t stb_strscpy(char *d, const char *s, size_t n) +{ + size_t len = strlen(s); + if (len >= n) { + if (n) d[0] = 0; + return 0; + } + strcpy(d,s); + return len + 1; +} + char *stb_plural(int n) { return n == 1 ? "" : "s"; @@ -5874,7 +5901,7 @@ STB_EXTERN int stb_wildmatchi(char *expr, char *candidate); static char **readdir_raw(char *dir, int return_subdirs, char *mask) { char **results = NULL; - char buffer[512], with_slash[512]; + char buffer[4096], with_slash[4096]; size_t n; #ifdef _MSC_VER @@ -5892,25 +5919,28 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) DIR *z; #endif - strcpy(buffer,dir); + n = stb_strscpy(buffer,dir,sizeof(buffer)); + if (!n || n >= sizeof(buffer)) + return NULL; stb_fixpath(buffer); - n = strlen(buffer); + n--; if (n > 0 && (buffer[n-1] != '/')) { buffer[n++] = '/'; } buffer[n] = 0; - strcpy(with_slash, buffer); + if (!stb_strscpy(with_slash,buffer,sizeof(with_slash))) + return NULL; #ifdef _MSC_VER - strcpy(buffer+n, "*.*"); + if (!stb_strscpy(buffer+n,"*.*",sizeof(buffer)-n)) + return NULL; ws = stb__from_utf8(buffer); z = _wfindfirst((const wchar_t *)ws, &data); #else z = opendir(dir); #endif - if (z != none) { int nonempty = STB_TRUE; #ifndef _MSC_VER @@ -5931,17 +5961,18 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) is_subdir = !!(data.attrib & _A_SUBDIR); #else char *name = data->d_name; - strcpy(buffer+n,name); - DIR *y = opendir(buffer); - is_subdir = (y != NULL); - if (y != NULL) closedir(y); + if (!stb_strscpy(buffer+n,name,sizeof(buffer)-n)) + break; + // Could follow DT_LNK, but would need to check for recursive links. + is_subdir = !!(data->d_type & DT_DIR); #endif - + if (is_subdir == return_subdirs) { if (!is_subdir || !isdotdirname(name)) { if (!mask || stb_wildmatchi(mask, name)) { - char buffer[512],*p=buffer; - sprintf(buffer, "%s%s", with_slash, name); + char buffer[4096],*p=buffer; + if ( stb_snprintf(buffer, sizeof(buffer), "%s%s", with_slash, name) < 0 ) + break; if (buffer[0] == '.' && buffer[1] == '/') p = buffer+2; stb_arr_push(results, strdup(p)); From 702c5bfee860946b1c9c513a7259a74e0e61f999 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 3 Nov 2015 15:10:58 -0800 Subject: [PATCH 144/522] Update other_libs.md --- docs/other_libs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2931064..f9af1b8 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -14,7 +14,8 @@ free to tell me about their quality.) _Newest additions are in italics._ - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C +- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) +- _**hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain)_ Not public domain: From d113bea69a84b1440227db923a4a5fc7c1456e1b Mon Sep 17 00:00:00 2001 From: Stephen Olsen Date: Wed, 4 Nov 2015 14:02:33 -0600 Subject: [PATCH 145/522] typo in shader Should be mat4 or mat4x4, not mat44 --- stb_voxel_render.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 29f6fb7..9767078 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -1590,7 +1590,7 @@ static const char *stbvox_vertex_program = "uniform vec3 normal_table[32];\n" #ifndef STBVOX_CONFIG_OPENGL_MODELVIEW - "uniform mat44 model_view;\n" + "uniform mat4x4 model_view;\n" #endif // fragment output data From 76b8ff0051194f554413a791dde0be7974ef12ee Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 04:47:36 -0800 Subject: [PATCH 146/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index f9af1b8..b62e3ea 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -12,6 +12,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) - **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) +- _**math** [sobol](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain)_ - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) From 450db24449ace1f50f29642b4955acecbe418744 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 04:47:49 -0800 Subject: [PATCH 147/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index b62e3ea..684c561 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -12,7 +12,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) - **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) -- _**math** [sobol](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain)_ +- _**math** [sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain)_ - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) From b6602ab0850f378154da3395c621862acbed16be Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 04:51:38 -0800 Subject: [PATCH 148/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 684c561..8530770 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -11,8 +11,8 @@ free to tell me about their quality.) _Newest additions are in italics._ - **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) - **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) - **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) +- _**geometry** [sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain)_ - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) -- _**math** [sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain)_ - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) From a44e950d9a0626d16da0622cc4bb63fd58ccef6d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 04:58:42 -0800 Subject: [PATCH 149/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8530770..45a21e8 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -14,6 +14,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - _**geometry** [sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain)_ - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) +- **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) - _**hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain)_ @@ -64,7 +65,6 @@ this! But you might like them anyway: - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) - **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) - **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) -- **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (zlib license) - **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) - _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license)_ - _**data structures** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license)_ From 20eea21e0114a79bfa179f0cf7db5242ca31f220 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 05:11:34 -0800 Subject: [PATCH 150/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 45a21e8..10cbce1 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -17,6 +17,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) +- _**misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) - _**hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain)_ Not public domain: From d4cea6123a0fa8638acef6ea28d99336fed9d174 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 05:13:00 -0800 Subject: [PATCH 151/522] Update other_libs.md --- docs/other_libs.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 10cbce1..32e804f 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -64,7 +64,6 @@ this! But you might like them anyway: - **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- **parsing** [Zange](https://github.com/vurtun/zange/blob/master/json.c): another JSON parser (MIT license) - **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) - **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) - _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license)_ From fa9a6e4e0a99bda20688d4df9d1d1588a790e35e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 06:48:42 -0800 Subject: [PATCH 152/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 32e804f..2827045 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -64,6 +64,7 @@ this! But you might like them anyway: - **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) +- _**parsing** [jzon.h](https://github.com/Zguy/Jzon): JSON parser, C++ (MIT license) - **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) - **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) - _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license)_ From 3f73dfd7ce055de51fae53c21b7887cc90d86f4d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 Nov 2015 06:49:02 -0800 Subject: [PATCH 153/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2827045..96651bd 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -64,7 +64,7 @@ this! But you might like them anyway: - **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- _**parsing** [jzon.h](https://github.com/Zguy/Jzon): JSON parser, C++ (MIT license) +- _**parsing** [jzon.h](https://github.com/Zguy/Jzon): JSON parser, C++ (MIT license)_ - **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) - **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) - _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license)_ From 8603c6e8095e1a10a2855c6029ba4bf65d77e827 Mon Sep 17 00:00:00 2001 From: svdijk Date: Thu, 5 Nov 2015 23:32:40 +0100 Subject: [PATCH 154/522] stb_image.h: Only define stbi__l2h_{gamme,scale} when needed. This fixes a (well, actually the only) compiler warning. --- stb_image.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 0a9de39..0fcf37a 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1186,14 +1186,15 @@ STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void #endif } -static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; +#ifndef STBI_NO_LINEAR static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; -#ifndef STBI_NO_LINEAR STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } #endif +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } From 9f1a587d22e8a11f7ce2b00dcc9699520343daf3 Mon Sep 17 00:00:00 2001 From: svdijk Date: Thu, 5 Nov 2015 23:34:44 +0100 Subject: [PATCH 155/522] stb_image.h: Fix/add some comments. --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 0fcf37a..b9a6d64 100644 --- a/stb_image.h +++ b/stb_image.h @@ -461,12 +461,12 @@ STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, #ifndef STBI_NO_HDR STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); STBIDEF void stbi_hdr_to_ldr_scale(float scale); -#endif +#endif // STBI_NO_HDR #ifndef STBI_NO_LINEAR STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); STBIDEF void stbi_ldr_to_hdr_scale(float scale); -#endif // STBI_NO_HDR +#endif // STBI_NO_LINEAR // stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); From 31eff2dcaf568aec77112d27e772e2f1223de2ae Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 00:37:52 -0800 Subject: [PATCH 156/522] fix bug in integer parsing --- stb_c_lexer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index 1cf53e4..c1c4279 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -634,7 +634,7 @@ int stb_c_lexer_get_token(stb_lexer *lexer) if (p[1] == 'x' || p[1] == 'X') { char *q = p+2; #ifdef STB__CLEX_use_stdlib - lexer->int_number = strtol((char *) p, (char **) q, 16); + lexer->int_number = strtol((char *) p, (char **) &q, 16); #else stb__clex_int n=0; while (q != lexer->eof) { From 0615df6c9b1eadfcbd0e65a6ca1f4ae3947919ee Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 00:45:17 -0800 Subject: [PATCH 157/522] allows comments in pgm/ppm headers --- stb_image.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 0a9de39..354807b 100644 --- a/stb_image.h +++ b/stb_image.h @@ -195,7 +195,7 @@ Omar Cornut (1/2/4-bit PNG) Ken Hamada Nicolas Guillemot (vertical flip) Cort Stratton Richard Mitton (16-bit PSD) Blazej Dariusz Roszkowski - Thibault Reuille + Junggon Kim (PNM comments) Thibault Reuille Paul Du Bois Guillaume George Jerry Jansson @@ -6222,8 +6222,16 @@ static int stbi__pnm_isspace(char c) static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) { - while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) - *c = (char) stbi__get8(s); + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } } static int stbi__pnm_isdigit(char c) From 6382e49063dd302785bf1d0055fdf15bc65f6359 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 00:54:49 -0800 Subject: [PATCH 158/522] don't crash if out of memory allocating a new active edge (assert in debug) --- stb_truetype.h | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index bf546c3..b57043e 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -49,7 +49,7 @@ // // VERSION HISTORY // -// 1.09 (????-??-??) warning fix +// 1.09 (????-??-??) warning fix; avoid crash on outofmem // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; @@ -1674,6 +1674,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); if (!z) return z; // round dx down to avoid overshooting @@ -1695,6 +1696,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); //STBTT_assert(e->y0 <= start_point); if (!z) return z; z->fdx = dxdy; @@ -1819,21 +1821,23 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, while (e->y0 <= scan_y) { if (e->y1 > scan_y) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); - // find insertion point - if (active == NULL) - active = z; - else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - stbtt__active_edge *p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } } } ++e; @@ -2103,10 +2107,12 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, while (e->y0 <= scan_y_bottom) { if (e->y0 != e->y1) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - STBTT_assert(z->ey >= scan_y_top); - // insert at front - z->next = active; - active = z; + if (z != NULL) { + STBTT_assert(z->ey >= scan_y_top); + // insert at front + z->next = active; + active = z; + } } ++e; } From 16fc63404d5b9256564feb54bcb44f255a6efdda Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 01:03:37 -0800 Subject: [PATCH 159/522] suppress bogus static analysis warning --- stb_truetype.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stb_truetype.h b/stb_truetype.h index b57043e..0b1e3b5 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -43,6 +43,7 @@ // Giumo X. Clanjor // Higor Euripedes // Thomas Fields +// Derek Vinyard // // Misc other: // Ryan Gordon @@ -2714,6 +2715,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_w = w - kernel_width; int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < h; ++j) { int i; unsigned int total; @@ -2775,6 +2777,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_h = h - kernel_width; int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < w; ++j) { int i; unsigned int total; From 876aea3dbe0e56984f7336e55698c06c9346c8e8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 01:22:30 -0800 Subject: [PATCH 160/522] refactor bmp header parser for sharing with stbi_info --- stb_image.h | 136 ++++++++++++++++++++++++++++----------------- tests/image_test.c | 4 +- 2 files changed, 87 insertions(+), 53 deletions(-) diff --git a/stb_image.h b/stb_image.h index 354807b..df78c2f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4598,19 +4598,22 @@ static int stbi__shiftsigned(int v, int shift, int bits) return result; } -static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +typedef struct { - stbi_uc *out; - unsigned int mr=0,mg=0,mb=0,ma=0, all_a=255; - stbi_uc pal[256][4]; - int psize=0,i,j,compress=0,width; - int bpp, flip_vertically, pad, target, offset, hsz; + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); stbi__get32le(s); // discard filesize stbi__get16le(s); // discard reserved stbi__get16le(s); // discard reserved - offset = stbi__get32le(s); - hsz = stbi__get32le(s); + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { s->img_x = stbi__get16le(s); @@ -4620,15 +4623,10 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int s->img_y = stbi__get32le(s); } if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); - bpp = stbi__get16le(s); - if (bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); - flip_vertically = ((int) s->img_y) > 0; - s->img_y = abs((int) s->img_y); - if (hsz == 12) { - if (bpp < 24) - psize = (offset - 14 - 24) / 3; - } else { - compress = stbi__get32le(s); + info->bpp = stbi__get16le(s); + if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); + if (hsz != 12) { + int compress = stbi__get32le(s); if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); stbi__get32le(s); // discard sizeof stbi__get32le(s); // discard hres @@ -4642,26 +4640,26 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int stbi__get32le(s); stbi__get32le(s); } - if (bpp == 16 || bpp == 32) { - mr = mg = mb = 0; + if (info->bpp == 16 || info->bpp == 32) { + info->mr = info->mg = info->mb = 0; if (compress == 0) { - if (bpp == 32) { - mr = 0xffu << 16; - mg = 0xffu << 8; - mb = 0xffu << 0; - ma = 0xffu << 24; - all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 } else { - mr = 31u << 10; - mg = 31u << 5; - mb = 31u << 0; + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; } } else if (compress == 3) { - mr = stbi__get32le(s); - mg = stbi__get32le(s); - mb = stbi__get32le(s); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); // not documented, but generated by photoshop and handled by mspaint - if (mr == mg && mg == mb) { + if (info->mr == info->mg && info->mg == info->mb) { // ?!?!? return stbi__errpuc("bad BMP", "bad BMP"); } @@ -4669,11 +4667,13 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int return stbi__errpuc("bad BMP", "bad BMP"); } } else { - STBI_ASSERT(hsz == 108 || hsz == 124); - mr = stbi__get32le(s); - mg = stbi__get32le(s); - mb = stbi__get32le(s); - ma = stbi__get32le(s); + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); stbi__get32le(s); // discard color space for (i=0; i < 12; ++i) stbi__get32le(s); // discard color space parameters @@ -4684,35 +4684,68 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int stbi__get32le(s); // discard reserved } } - if (bpp < 16) - psize = (offset - 14 - hsz) >> 2; } + return (void *) 1; +} + + +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + s->img_n = ma ? 4 : 3; if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 target = req_comp; else target = s->img_n; // if they want monochrome, we'll post-convert + out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); if (!out) return stbi__errpuc("outofmem", "Out of memory"); - if (bpp < 16) { + if (info.bpp < 16) { int z=0; if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } for (i=0; i < psize; ++i) { pal[i][2] = stbi__get8(s); pal[i][1] = stbi__get8(s); pal[i][0] = stbi__get8(s); - if (hsz != 12) stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); pal[i][3] = 255; } - stbi__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); - if (bpp == 4) width = (s->img_x + 1) >> 1; - else if (bpp == 8) width = s->img_x; + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } pad = (-width)&3; for (j=0; j < (int) s->img_y; ++j) { for (i=0; i < (int) s->img_x; i += 2) { int v=stbi__get8(s),v2=0; - if (bpp == 4) { + if (info.bpp == 4) { v2 = v & 15; v >>= 4; } @@ -4721,7 +4754,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int out[z++] = pal[v][2]; if (target == 4) out[z++] = 255; if (i+1 == (int) s->img_x) break; - v = (bpp == 8) ? stbi__get8(s) : v2; + v = (info.bpp == 8) ? stbi__get8(s) : v2; out[z++] = pal[v][0]; out[z++] = pal[v][1]; out[z++] = pal[v][2]; @@ -4733,14 +4766,14 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int z = 0; int easy=0; - stbi__skip(s, offset - 14 - hsz); - if (bpp == 24) width = 3 * s->img_x; - else if (bpp == 16) width = 2*s->img_x; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; else /* bpp = 32 and pad = 0 */ width=0; pad = (-width) & 3; - if (bpp == 24) { + if (info.bpp == 24) { easy = 1; - } else if (bpp == 32) { + } else if (info.bpp == 32) { if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) easy = 2; } @@ -4765,6 +4798,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int if (target == 4) out[z++] = a; } } else { + int bpp = info.bpp; for (i=0; i < (int) s->img_x; ++i) { stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); int a; diff --git a/tests/image_test.c b/tests/image_test.c index 9bb1832..86d3b46 100644 --- a/tests/image_test.c +++ b/tests/image_test.c @@ -7,7 +7,7 @@ #define STB_DEFINE #include "stb.h" -#define PNGSUITE_PRIMARY +//#define PNGSUITE_PRIMARY #if 0 void test_ycbcr(void) @@ -65,7 +65,7 @@ int main(int argc, char **argv) int w,h; //test_ycbcr(); - #if 1 + #if 0 // test hdr asserts for (h=0; h < 100; h += 2) for (w=0; w < 200; ++w) From 297ff6285909c510c27752785083d497ee1dbf7c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 13:09:16 -0800 Subject: [PATCH 161/522] change bmp info to use common header parser --- stb_image.h | 34 +++++++++++----------------------- tests/image_test.c | 6 ++++-- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/stb_image.h b/stb_image.h index df78c2f..429f2ff 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6088,29 +6088,17 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) #ifndef STBI_NO_BMP static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) { - int hsz; - if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') { - stbi__rewind( s ); - return 0; - } - stbi__skip(s,12); - hsz = stbi__get32le(s); - if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) { - stbi__rewind( s ); - return 0; - } - if (hsz == 12) { - *x = stbi__get16le(s); - *y = stbi__get16le(s); - } else { - *x = stbi__get32le(s); - *y = stbi__get32le(s); - } - if (stbi__get16le(s) != 1) { - stbi__rewind( s ); - return 0; - } - *comp = stbi__get16le(s) / 8; + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + *x = s->img_x; + *y = s->img_y; + *comp = info.ma ? 4 : 3; return 1; } #endif diff --git a/tests/image_test.c b/tests/image_test.c index 86d3b46..b449744 100644 --- a/tests/image_test.c +++ b/tests/image_test.c @@ -81,15 +81,17 @@ int main(int argc, char **argv) for (i=1; i < argc; ++i) { int res; + int w2,h2,n2; unsigned char *data; printf("%s\n", argv[i]); - res = stbi_info(argv[1], &w, &h, &n); + res = stbi_info(argv[1], &w2, &h2, &n2); data = stbi_load(argv[i], &w, &h, &n, 4); if (data) free(data); else printf("Failed &n\n"); data = stbi_load(argv[i], &w, &h, 0, 1); if (data) free(data); else printf("Failed 1\n"); data = stbi_load(argv[i], &w, &h, 0, 2); if (data) free(data); else printf("Failed 2\n"); data = stbi_load(argv[i], &w, &h, 0, 3); if (data) free(data); else printf("Failed 3\n"); - data = stbi_load(argv[i], &w, &h, 0, 4); + data = stbi_load(argv[i], &w, &h, &n, 4); assert(data); + assert(w == w2 && h == h2 && n == n2); assert(res); if (data) { char fname[512]; From 2073403a5f54eda44090bc62d0907e07ba73bde5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 13:09:30 -0800 Subject: [PATCH 162/522] fix two setup crashes found by fuzz testing --- stb_vorbis.c | 46 +++++++++++++++++++++++++++------------------ tests/test_vorbis.c | 2 +- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 98e96fb..ac22315 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -556,9 +556,11 @@ enum STBVorbisError #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) #include #endif -#else +#else // STB_VORBIS_NO_CRT #define NULL 0 -#endif +#endif // STB_VORBIS_NO_CRT + +#include #if !defined(_MSC_VER) && !(defined(__MINGW32__) && defined(__forceinline)) #if __GNUC__ @@ -3645,14 +3647,15 @@ static int start_decoder(vorb *f) get32(f); // bitrate_nominal get32(f); // bitrate_minimum x = get8(f); - { int log0,log1; - log0 = x & 15; - log1 = x >> 4; - f->blocksize_0 = 1 << log0; - f->blocksize_1 = 1 << log1; - if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); - if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); - if (log0 > log1) return error(f, VORBIS_invalid_setup); + { + int log0,log1; + log0 = x & 15; + log1 = x >> 4; + f->blocksize_0 = 1 << log0; + f->blocksize_1 = 1 << log1; + if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); + if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); + if (log0 > log1) return error(f, VORBIS_invalid_setup); } // framing_flag @@ -3828,6 +3831,7 @@ static int start_decoder(vorb *f) } else { c->lookup_values = c->entries * c->dimensions; } + if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup); mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); if (mults == NULL) return error(f, VORBIS_outofmem); for (j=0; j < (int) c->lookup_values; ++j) { @@ -3848,21 +3852,27 @@ static int start_decoder(vorb *f) if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } len = sparse ? c->sorted_entries : c->entries; for (j=0; j < len; ++j) { - int z = sparse ? c->sorted_values[j] : j, div=1; + unsigned int z = sparse ? c->sorted_values[j] : j; + unsigned int div=1; for (k=0; k < c->dimensions; ++k) { int off = (z / div) % c->lookup_values; - c->multiplicands[j*c->dimensions + k] = - #ifndef STB_VORBIS_CODEBOOK_FLOATS - mults[off]; - #else - mults[off]*c->delta_value + c->minimum_value; + #ifndef STB_VORBIS_CODEBOOK_FLOATS + c->multiplicands[j*c->dimensions + k] = mults[off]; + #else + c->multiplicands[j*c->dimensions + k] = mults[off]*c->delta_value + c->minimum_value; // in this case (and this case only) we could pre-expand c->sequence_p, // and throw away the decode logic for it; have to ALSO do // it in the case below, but it can only be done if // STB_VORBIS_CODEBOOK_FLOATS // !STB_VORBIS_DIVIDES_IN_CODEBOOK - #endif - div *= c->lookup_values; + #endif + if (k+1 < c->dimensions) { + if (div > UINT_MAX / (unsigned int) c->lookup_values) { + setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); + return error(f, VORBIS_invalid_setup); + } + div *= c->lookup_values; + } } } setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); diff --git a/tests/test_vorbis.c b/tests/test_vorbis.c index 5841381..f24376d 100644 --- a/tests/test_vorbis.c +++ b/tests/test_vorbis.c @@ -8,7 +8,7 @@ extern void stb_vorbis_dumpmem(void); int main(int argc, char **argv) { size_t memlen; - unsigned char *mem = stb_fileu("c:/x/theme_03.ogg", &memlen); + unsigned char *mem = stb_fileu("c:/x/vorbis/1.ogg", &memlen); int chan, samplerate; short *output; int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); From 69a318bdb3bbaf7327a87bd18ec7d9b223091fe6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 13:20:55 -0800 Subject: [PATCH 163/522] fix two invalid-file crashes found by fuzz testing --- stb_vorbis.c | 3 +++ tests/test_vorbis.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index ac22315..d902894 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3715,6 +3715,8 @@ static int start_decoder(vorb *f) ordered = get_bits(f,1); c->sparse = ordered ? 0 : get_bits(f,1); + if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup); + if (c->sparse) lengths = (uint8 *) setup_temp_malloc(f, c->entries); else @@ -3998,6 +4000,7 @@ static int start_decoder(vorb *f) if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); r->begin = get_bits(f, 24); r->end = get_bits(f, 24); + if (r->end < r->begin) return error(f, VORBIS_invalid_setup); r->part_size = get_bits(f,24)+1; r->classifications = get_bits(f,6)+1; r->classbook = get_bits(f,8); diff --git a/tests/test_vorbis.c b/tests/test_vorbis.c index f24376d..0d0c0cf 100644 --- a/tests/test_vorbis.c +++ b/tests/test_vorbis.c @@ -8,7 +8,7 @@ extern void stb_vorbis_dumpmem(void); int main(int argc, char **argv) { size_t memlen; - unsigned char *mem = stb_fileu("c:/x/vorbis/1.ogg", &memlen); + unsigned char *mem = stb_fileu("c:/x/vorbis/4.ogg", &memlen); int chan, samplerate; short *output; int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); From ea88e59b5dd48bc2179dd7db537923f9edbba707 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 13:45:33 -0800 Subject: [PATCH 164/522] fix invalid handling of truncated end-of-file indicator --- stb_vorbis.c | 7 +++++-- tests/test_vorbis.c | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index d902894..04f082e 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -906,7 +906,7 @@ static void *setup_malloc(vorb *f, int sz) static void setup_free(vorb *f, void *p) { - if (f->alloc.alloc_buffer) return; // do nothing; setup mem is not a stack + if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack free(p); } @@ -3219,6 +3219,7 @@ static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, in *p_right_start = window_center; *p_right_end = n; } + return TRUE; } @@ -3457,7 +3458,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { uint32 current_end = f->known_loc_for_packet - (n-right_end); // then let's infer the size of the (probably) short final frame - if (current_end < f->current_loc + right_end) { + if (current_end < f->current_loc + (right_end-left_start)) { if (current_end < f->current_loc) { // negative truncation, that's impossible! *len = 0; @@ -3465,6 +3466,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, *len = current_end - f->current_loc; } *len += left_start; + if (*len > right_end) *len = right_end; // this should never happen f->current_loc += *len; return TRUE; } @@ -3482,6 +3484,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->alloc.alloc_buffer) assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); *len = right_end; // ignore samples after the window goes to 0 + return TRUE; } diff --git a/tests/test_vorbis.c b/tests/test_vorbis.c index 0d0c0cf..74566da 100644 --- a/tests/test_vorbis.c +++ b/tests/test_vorbis.c @@ -8,7 +8,7 @@ extern void stb_vorbis_dumpmem(void); int main(int argc, char **argv) { size_t memlen; - unsigned char *mem = stb_fileu("c:/x/vorbis/4.ogg", &memlen); + unsigned char *mem = stb_fileu("c:/x/vorbis/5.ogg", &memlen); int chan, samplerate; short *output; int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); From 70b33e99f0487d7d8665b483aff3cf2e70a4148f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 14:04:56 -0800 Subject: [PATCH 165/522] fix crash from invalid file --- stb_vorbis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 04f082e..54481e7 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1906,7 +1906,7 @@ static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **o } } else { i=0; - if (c_inter == 1) { + if (c_inter == 1 && i < effective) { float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; if (outputs[c_inter]) outputs[c_inter][p_inter] += val; @@ -2176,7 +2176,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int goto done; #else // saves 1% - if (!codebook_decode_deinterleave_repeat_2(f, book, residue_buffers, &c_inter, &p_inter, n, r->part_size)) + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; #endif stb_prof(7); From bdac1d2ab43823725fcd701e6310fbc0efd942de Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 16:01:40 -0800 Subject: [PATCH 166/522] fix two crashes in invalid files --- stb_vorbis.c | 83 ++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 54481e7..5bf8bae 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -579,6 +579,13 @@ enum STBVorbisError #endif +#if 0 +#include +#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1]) +#else +#define CHECK(f) ((void) 0) +#endif + #define MAX_BLOCKSIZE_LOG 13 // from specification #define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) @@ -833,13 +840,6 @@ struct stb_vorbis int channel_buffer_end; }; -extern int my_prof(int slot); -//#define stb_prof my_prof - -#ifndef stb_prof -#define stb_prof(x) ((void) 0) -#endif - #if defined(STB_VORBIS_NO_PUSHDATA_API) #define IS_PUSH_MODE(f) FALSE #elif defined(STB_VORBIS_NO_PULLDATA_API) @@ -1894,7 +1894,6 @@ static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **o { z *= c->dimensions; - stb_prof(11); if (c->sequence_p) { // haven't optimized this case because I don't have any examples for (i=0; i < effective; ++i) { @@ -2078,15 +2077,17 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y #endif ady -= abs(base) * adx; if (x1 > n) x1 = n; - LINE_OP(output[x], inverse_db_table[y]); - for (++x; x < x1; ++x) { - err += ady; - if (err >= adx) { - err -= adx; - y += sy; - } else - y += base; + if (x < x1) { LINE_OP(output[x], inverse_db_table[y]); + for (++x; x < x1; ++x) { + err += ady; + if (err >= adx) { + err -= adx; + y += sy; + } else + y += base; + LINE_OP(output[x], inverse_db_table[y]); + } } } @@ -2125,7 +2126,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); #endif - stb_prof(2); + CHECK(f); + for (i=0; i < ch; ++i) if (!do_not_decode[i]) memset(residue_buffers[i], 0, sizeof(float) * n); @@ -2137,11 +2139,9 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int if (j == ch) goto done; - stb_prof(3); for (pass=0; pass < 8; ++pass) { int pcount = 0, class_set = 0; if (ch == 2) { - stb_prof(13); while (pcount < part_read) { int z = r->begin + pcount*r->part_size; int c_inter = (z & 1), p_inter = z>>1; @@ -2159,7 +2159,6 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } #endif } - stb_prof(5); for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { int z = r->begin + pcount*r->part_size; #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE @@ -2170,7 +2169,6 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int b = r->residue_books[c][pass]; if (b >= 0) { Codebook *book = f->codebooks + b; - stb_prof(20); // accounts for X time #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; @@ -2179,14 +2177,12 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; #endif - stb_prof(7); } else { z += r->part_size; c_inter = z & 1; p_inter = z >> 1; } } - stb_prof(8); #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE ++class_set; #endif @@ -2219,10 +2215,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int b = r->residue_books[c][pass]; if (b >= 0) { Codebook *book = f->codebooks + b; - stb_prof(22); if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; - stb_prof(3); } else { z += r->part_size; c_inter = 0; @@ -2261,10 +2255,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int b = r->residue_books[c][pass]; if (b >= 0) { Codebook *book = f->codebooks + b; - stb_prof(22); if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; - stb_prof(3); } else { z += r->part_size; c_inter = z % ch; @@ -2279,7 +2271,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } goto done; } - stb_prof(9); + CHECK(f); for (pass=0; pass < 8; ++pass) { int pcount = 0, class_set=0; @@ -2328,7 +2320,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } } done: - stb_prof(0); + CHECK(f); temp_alloc_restore(f,temp_alloc_point); } @@ -3142,13 +3134,16 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f int hx = g->Xlist[j]; if (lx != hx) draw_line(target, lx,ly, hx,hy, n2); + CHECK(f); lx = hx, ly = hy; } } - if (lx < n2) + if (lx < n2) { // optimization of: draw_line(target, lx,ly, n,ly, n2); for (j=lx; j < n2; ++j) LINE_OP(target[j], inverse_db_table[ly]); + CHECK(f); + } } return TRUE; } @@ -3238,7 +3233,8 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, // FLOORS n2 = n >> 1; - stb_prof(1); + CHECK(f); + for (i=0; i < f->channels; ++i) { int s = map->chan[i].mux, floor; zero_channel[i] = FALSE; @@ -3330,7 +3326,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, // at this point we've decoded the floor into buffer } } - stb_prof(0); + CHECK(f); // at this point we've decoded all floors if (f->alloc.alloc_buffer) @@ -3343,6 +3339,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; } + CHECK(f); // RESIDUE DECODE for (i=0; i < map->submaps; ++i) { float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; @@ -3367,9 +3364,9 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->alloc.alloc_buffer) assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + CHECK(f); // INVERSE COUPLING - stb_prof(14); for (i = map->coupling_steps-1; i >= 0; --i) { int n2 = n >> 1; float *m = f->channel_buffers[map->chan[i].magnitude]; @@ -3390,10 +3387,10 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, a[j] = a2; } } + CHECK(f); // finish decoding the floors #ifndef STB_VORBIS_NO_DEFER_FLOOR - stb_prof(15); for (i=0; i < f->channels; ++i) { if (really_zero_channel[i]) { memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); @@ -3413,10 +3410,10 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, #endif // INVERSE MDCT - stb_prof(16); + CHECK(f); for (i=0; i < f->channels; ++i) inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); - stb_prof(0); + CHECK(f); // this shouldn't be necessary, unless we exited on an error // and want to flush to get to the next packet @@ -3484,6 +3481,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->alloc.alloc_buffer) assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); *len = right_end; // ignore samples after the window goes to 0 + CHECK(f); return TRUE; } @@ -3707,6 +3705,7 @@ static int start_decoder(vorb *f) int total=0; uint8 *lengths; Codebook *c = f->codebooks+i; + CHECK(f); x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); @@ -3778,6 +3777,7 @@ static int start_decoder(vorb *f) c->sorted_entries = sorted_count; values = NULL; + CHECK(f); if (!c->sparse) { c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); if (!c->codewords) return error(f, VORBIS_outofmem); @@ -3823,6 +3823,7 @@ static int start_decoder(vorb *f) compute_accelerated_huffman(c); + CHECK(f); c->lookup_type = get_bits(f, 4); if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); if (c->lookup_type > 0) { @@ -3886,6 +3887,7 @@ static int start_decoder(vorb *f) else #endif { + CHECK(f); c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } #ifndef STB_VORBIS_CODEBOOK_FLOATS @@ -3900,14 +3902,17 @@ static int start_decoder(vorb *f) skip:; #endif + CHECK(f); #ifdef STB_VORBIS_CODEBOOK_FLOATS if (c->lookup_type == 2 && c->sequence_p) { - for (j=1; j < (int) c->lookup_values; ++j) - c->multiplicands[j] = c->multiplicands[j-1]; + for (j=1; j < (int) (c->sparse ? c->sorted_entries : c->lookup_values); ++j) + c->multiplicands[j] += c->multiplicands[j-1]; + CHECK(f); c->sequence_p = 0; } #endif } + CHECK(f); } // time domain transfers (notused) @@ -4187,6 +4192,7 @@ static void vorbis_deinit(stb_vorbis *p) } if (p->codebooks) { + CHECK(p); for (i=0; i < p->codebook_count; ++i) { Codebook *c = p->codebooks + i; setup_free(p, c->codeword_lengths); @@ -4205,6 +4211,7 @@ static void vorbis_deinit(stb_vorbis *p) setup_free(p, p->mapping[i].chan); setup_free(p, p->mapping); } + CHECK(p); for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) { setup_free(p, p->channel_buffers[i]); setup_free(p, p->previous_window[i]); From bc2219e1b3cfcaf511242f009186d13f78c8885d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 16:22:07 -0800 Subject: [PATCH 167/522] fix multiple crashes on invalid files --- stb_vorbis.c | 20 ++++++++++++++++---- tests/test_vorbis.c | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 5bf8bae..731b6bd 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,8 +1,11 @@ -// Ogg Vorbis audio decoder - v1.06 - public domain +// Ogg Vorbis audio decoder - v1.07 - public domain // http://nothings.org/stb_vorbis/ // -// Written by Sean Barrett in 2007, last updated in 2014 -// Sponsored by RAD Game Tools. +// Original version written by Sean Barrett in 2007. +// +// Originally sponsored by RAD Game Tools. Seeking sponsored +// by Phillip Bennefall, Marc Andersen, Elias Software, vgstorm.com, +// Aras Pranckevicius, and Sean Barrett. // // LICENSE // @@ -30,11 +33,13 @@ // Laurent Gomila Marc LeBlanc Ronny Chevalier // Bernhard Wodo Evan Balster "alxprd"@github // Tom Beaumont Ingo Leitgeb Nicolas Guillemot +// Phillip Bennefall // (If you reported a bug but do not appear in this list, it is because // someone else reported the bug before you. There were too many of you to // list them all because I was lax about updating for a long time, sorry.) // // Partial history: +// 1.07 - 2015/11/08 - fixes for crashes on invalid files // 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) // some crash fixes when out of memory or with corrupt files // fix some inappropriately signed shifts @@ -1057,10 +1062,12 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) while (z > 0 && !available[z]) --z; if (z == 0) { return FALSE; } res = available[z]; + assert(z >= 0 && z < 32); available[z] = 0; add_entry(c, bit_reverse(res), i, m++, len[i], values); // propogate availability up the tree if (z != len[i]) { + assert(len[i] >= 0 && len[i] < 32); for (y=len[i]; y > z; --y) { assert(available[y] == 0); available[y] = res + (1 << (32-y)); @@ -1586,7 +1593,9 @@ static int codebook_decode_scalar_raw(vorb *f, Codebook *c) int i; prep_huffman(f); - assert(c->sorted_codewords || c->codewords); + if (c->codewords == NULL && c->sorted_codewords == NULL) + return -1; + // cases to use binary search: sorted_codewords && !c->codewords // sorted_codewords && c->entries > 8 if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { @@ -3743,6 +3752,8 @@ static int start_decoder(vorb *f) if (present) { lengths[j] = get_bits(f, 5) + 1; ++total; + if (lengths[j] == 32) + return error(f, VORBIS_invalid_setup); } else { lengths[j] = NO_CODE; } @@ -4012,6 +4023,7 @@ static int start_decoder(vorb *f) r->part_size = get_bits(f,24)+1; r->classifications = get_bits(f,6)+1; r->classbook = get_bits(f,8); + if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup); for (j=0; j < r->classifications; ++j) { uint8 high_bits=0; uint8 low_bits=get_bits(f,3); diff --git a/tests/test_vorbis.c b/tests/test_vorbis.c index 74566da..a41c02c 100644 --- a/tests/test_vorbis.c +++ b/tests/test_vorbis.c @@ -8,7 +8,7 @@ extern void stb_vorbis_dumpmem(void); int main(int argc, char **argv) { size_t memlen; - unsigned char *mem = stb_fileu("c:/x/vorbis/5.ogg", &memlen); + unsigned char *mem = stb_fileu("c:/x/vorbis/stb_vorbis_crash.ogg", &memlen); int chan, samplerate; short *output; int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); From cf6f69cdc9ea4d0cc7f1fb86e724a31b1e61926b Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Sun, 8 Nov 2015 16:40:32 -0800 Subject: [PATCH 168/522] Fix the calculation of the input image shift when using subpixel regions. Includes some more tests which had incorrect results before and now work fine. --- stb_image_resize.h | 20 ++++++++++---------- tests/resample_test.cpp | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 4ce7ddb..fde37d8 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1004,31 +1004,31 @@ stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) } // What input pixels contribute to this output pixel? -static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float in_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) { float out_pixel_center = (float)n + 0.5f; float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; - float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; - float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + float in_pixel_influence_lowerbound = out_pixel_influence_lowerbound / scale_ratio + in_shift; + float in_pixel_influence_upperbound = out_pixel_influence_upperbound / scale_ratio + in_shift; - *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_center_of_out = out_pixel_center / scale_ratio + in_shift; *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); } // What output pixels does this input pixel contribute to? -static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float in_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) { float in_pixel_center = (float)n + 0.5f; float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; - float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; - float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + float out_pixel_influence_lowerbound = (in_pixel_influence_lowerbound - in_shift) * scale_ratio; + float out_pixel_influence_upperbound = (in_pixel_influence_upperbound - in_shift) * scale_ratio; - *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_center_of_in = (in_pixel_center - in_shift) * scale_ratio; *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); } @@ -2229,8 +2229,8 @@ static void stbir__calculate_transform(stbir__info *info, float s0, float t0, fl info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); - info->horizontal_shift = s0 * info->input_w / (s1 - s0); - info->vertical_shift = t0 * info->input_h / (t1 - t0); + info->horizontal_shift = s0 * info->input_w; + info->vertical_shift = t0 * info->input_h; } } diff --git a/tests/resample_test.cpp b/tests/resample_test.cpp index c42df7b..3bd3402 100644 --- a/tests/resample_test.cpp +++ b/tests/resample_test.cpp @@ -1,4 +1,5 @@ -#include +#include +#include #if defined(_WIN32) && _MSC_VER > 1200 #define STBIR_ASSERT(x) \ @@ -356,6 +357,30 @@ void test_subpixel(const char* file, float width_percent, float height_percent, free(output_data); } +void test_subpixel_really(const char* file, float width_percent, float height_percent, float s0, float t0, float s1, float t1) +{ + int w, h, n; + unsigned char* input_data = stbi_load(file, &w, &h, &n, 0); + + if (input_data == NULL) + return; + + int new_w = (int)(w * width_percent); + int new_h = (int)(h * height_percent); + + unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char)); + + stbir_resize_region(input_data, w, h, 0, output_data, new_w, new_h, 0, STBIR_TYPE_UINT8, n, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, s0, t0, s1, t1); + + stbi_image_free(input_data); + + char output[200]; + sprintf(output, "test-output/subpixel-really-%d-%d-%f-%f-%f-%f-%s", new_w, new_h, s0, t0, s1, t1, file); + stbi_write_png(output, new_w, new_h, n, output_data, 0); + + free(output_data); +} + unsigned int* pixel(unsigned int* buffer, int x, int y, int c, int w, int n) { return &buffer[y*w*n + x*n + c]; @@ -880,6 +905,19 @@ void test_suite(int argc, char **argv) stbir_resize(image88, 8, 8, 0, output88, 16, 4, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context); stbir_resize(image88, 8, 8, 0, output88, 16, 4, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, &g_context); + int res = 10; + for (int i = 0; i < res; i++) + { + float t = (float)i/res / 2; + test_subpixel_really(barbara, 0.5f, 0.5f, t, t, t+0.5f, t+0.5f); + } + + for (int i = 0; i < res; i++) + { + float t = (float)i/res / 2; + test_subpixel_really(barbara, 2, 2, t, t, t+0.5f, t+0.5f); + } + for (i = 0; i < 10; i++) test_subpixel(barbara, 0.5f, 0.5f, (float)i / 10, 1); From fe74a8c2232c76ee4e34328ea585846460218483 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 19:13:32 -0800 Subject: [PATCH 169/522] broken attempt at removign STB_VORBIS_CODEBOOK_FLOAT option --- stb_vorbis.c | 63 +++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 731b6bd..9030c31 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -493,14 +493,8 @@ enum STBVorbisError // trade off storage for speed. //#define STB_VORBIS_DIVIDES_IN_CODEBOOK -// STB_VORBIS_CODEBOOK_SHORTS -// The vorbis file format encodes VQ codebook floats as ax+b where a and -// b are floating point per-codebook constants, and x is a 16-bit int. -// Normally, stb_vorbis decodes them to floats rather than leaving them -// as 16-bit ints and computing ax+b while decoding. This is a speed/space -// tradeoff; you can save space by defining this flag. -#ifndef STB_VORBIS_CODEBOOK_SHORTS -#define STB_VORBIS_CODEBOOK_FLOATS +#ifdef STB_VORBIS_CODEBOOK_SHORTS +#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats" #endif // STB_VORBIS_DIVIDE_TABLE @@ -607,11 +601,7 @@ typedef signed int int32; #define FALSE 0 #endif -#ifdef STB_VORBIS_CODEBOOK_FLOATS typedef float codetype; -#else -typedef uint16 codetype; -#endif // @NOTE // @@ -1703,15 +1693,9 @@ static int codebook_decode_scalar(vorb *f, Codebook *c) // CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case // where we avoid one addition -#ifndef STB_VORBIS_CODEBOOK_FLOATS - #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value) - #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value) - #define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value) -#else - #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) - #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) - #define CODEBOOK_ELEMENT_BASE(c) (0) -#endif +#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value) +#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value) +#define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value) static int codebook_decode_start(vorb *f, Codebook *c) { @@ -3860,6 +3844,7 @@ static int start_decoder(vorb *f) #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK if (c->lookup_type == 1) { int len, sparse = c->sparse; + float last=0; // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop if (sparse) { if (c->sorted_entries == 0) goto skip; @@ -3873,16 +3858,11 @@ static int start_decoder(vorb *f) unsigned int div=1; for (k=0; k < c->dimensions; ++k) { int off = (z / div) % c->lookup_values; - #ifndef STB_VORBIS_CODEBOOK_FLOATS - c->multiplicands[j*c->dimensions + k] = mults[off]; - #else - c->multiplicands[j*c->dimensions + k] = mults[off]*c->delta_value + c->minimum_value; - // in this case (and this case only) we could pre-expand c->sequence_p, - // and throw away the decode logic for it; have to ALSO do - // it in the case below, but it can only be done if - // STB_VORBIS_CODEBOOK_FLOATS - // !STB_VORBIS_DIVIDES_IN_CODEBOOK - #endif + float val = mults[off]; + val = mults[off]*c->delta_value + c->minimum_value + last; + c->multiplicands[j*c->dimensions + k] = val; + if (c->sequence_p) + last = val; if (k+1 < c->dimensions) { if (div > UINT_MAX / (unsigned int) c->lookup_values) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); @@ -3898,15 +3878,16 @@ static int start_decoder(vorb *f) else #endif { + float last=0; CHECK(f); c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } - #ifndef STB_VORBIS_CODEBOOK_FLOATS - memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values); - #else - for (j=0; j < (int) c->lookup_values; ++j) - c->multiplicands[j] = mults[j] * c->delta_value + c->minimum_value; - #endif + for (j=0; j < (int) c->lookup_values; ++j) { + float val = mults[j] * c->delta_value + c->minimum_value + last; + c->multiplicands[j] = val; + if (c->sequence_p) + last = val; + } setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); } #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK @@ -3914,14 +3895,6 @@ static int start_decoder(vorb *f) #endif CHECK(f); - #ifdef STB_VORBIS_CODEBOOK_FLOATS - if (c->lookup_type == 2 && c->sequence_p) { - for (j=1; j < (int) (c->sparse ? c->sorted_entries : c->lookup_values); ++j) - c->multiplicands[j] += c->multiplicands[j-1]; - CHECK(f); - c->sequence_p = 0; - } - #endif } CHECK(f); } From 2b57ea95da349555469e5fd75c5c35e49d6060db Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 8 Nov 2015 19:16:25 -0800 Subject: [PATCH 170/522] fixed version of removed support for CODEBOOK_SHORTS --- stb_vorbis.c | 6 +++--- tests/test_vorbis.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 9030c31..ea753df 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1693,9 +1693,9 @@ static int codebook_decode_scalar(vorb *f, Codebook *c) // CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case // where we avoid one addition -#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value) -#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value) -#define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value) +#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_BASE(c) (0) static int codebook_decode_start(vorb *f, Codebook *c) { diff --git a/tests/test_vorbis.c b/tests/test_vorbis.c index a41c02c..d54ed23 100644 --- a/tests/test_vorbis.c +++ b/tests/test_vorbis.c @@ -8,10 +8,11 @@ extern void stb_vorbis_dumpmem(void); int main(int argc, char **argv) { size_t memlen; - unsigned char *mem = stb_fileu("c:/x/vorbis/stb_vorbis_crash.ogg", &memlen); + unsigned char *mem = stb_fileu("c:/x/sketch008.ogg", &memlen); int chan, samplerate; short *output; int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); + stb_filewrite("c:/x/sketch008.raw", output, samples*4); return 0; } #endif From a1ef3a1060a819aa48fd3fbf7547f0839fda4938 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Tue, 10 Nov 2015 11:25:59 -0800 Subject: [PATCH 171/522] Fix the calculation of the input image shift when using subpixel regions --- stb_image_resize.h | 4 +- tests/resample_test.cpp | 100 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 4ce7ddb..f7ce8f1 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -2229,8 +2229,8 @@ static void stbir__calculate_transform(stbir__info *info, float s0, float t0, fl info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); - info->horizontal_shift = s0 * info->input_w / (s1 - s0); - info->vertical_shift = t0 * info->input_h / (t1 - t0); + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); } } diff --git a/tests/resample_test.cpp b/tests/resample_test.cpp index c42df7b..86b7e5d 100644 --- a/tests/resample_test.cpp +++ b/tests/resample_test.cpp @@ -1,4 +1,5 @@ -#include +#include +#include #if defined(_WIN32) && _MSC_VER > 1200 #define STBIR_ASSERT(x) \ @@ -356,6 +357,54 @@ void test_subpixel(const char* file, float width_percent, float height_percent, free(output_data); } +void test_subpixel_region(const char* file, float width_percent, float height_percent, float s0, float t0, float s1, float t1) +{ + int w, h, n; + unsigned char* input_data = stbi_load(file, &w, &h, &n, 0); + + if (input_data == NULL) + return; + + int new_w = (int)(w * width_percent); + int new_h = (int)(h * height_percent); + + unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char)); + + stbir_resize_region(input_data, w, h, 0, output_data, new_w, new_h, 0, STBIR_TYPE_UINT8, n, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, s0, t0, s1, t1); + + stbi_image_free(input_data); + + char output[200]; + sprintf(output, "test-output/subpixel-region-%d-%d-%f-%f-%f-%f-%s", new_w, new_h, s0, t0, s1, t1, file); + stbi_write_png(output, new_w, new_h, n, output_data, 0); + + free(output_data); +} + +void test_subpixel_command(const char* file, float width_percent, float height_percent, float x_scale, float y_scale, float x_offset, float y_offset) +{ + int w, h, n; + unsigned char* input_data = stbi_load(file, &w, &h, &n, 0); + + if (input_data == NULL) + return; + + int new_w = (int)(w * width_percent); + int new_h = (int)(h * height_percent); + + unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char)); + + stbir_resize_subpixel(input_data, w, h, 0, output_data, new_w, new_h, 0, STBIR_TYPE_UINT8, n, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, x_scale, y_scale, x_offset, y_offset); + + stbi_image_free(input_data); + + char output[200]; + sprintf(output, "test-output/subpixel-command-%d-%d-%f-%f-%f-%f-%s", new_w, new_h, x_scale, y_scale, x_offset, y_offset, file); + stbi_write_png(output, new_w, new_h, n, output_data, 0); + + free(output_data); +} + unsigned int* pixel(unsigned int* buffer, int x, int y, int c, int w, int n) { return &buffer[y*w*n + x*n + c]; @@ -880,6 +929,55 @@ void test_suite(int argc, char **argv) stbir_resize(image88, 8, 8, 0, output88, 16, 4, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context); stbir_resize(image88, 8, 8, 0, output88, 16, 4, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, &g_context); + int barbara_width, barbara_height, barbara_channels; + stbi_image_free(stbi_load(barbara, &barbara_width, &barbara_height, &barbara_channels, 0)); + + int res = 10; + // Downscaling + for (int i = 0; i <= res; i++) + { + float t = (float)i/res; + float scale = 0.5; + float out_scale = 2.0/3; + float x_shift = (barbara_width*out_scale - barbara_width*scale) * t; + float y_shift = (barbara_height*out_scale - barbara_height*scale) * t; + + test_subpixel_command(barbara, scale, scale, out_scale, out_scale, x_shift, y_shift); + } + + // Upscaling + for (int i = 0; i <= res; i++) + { + float t = (float)i/res; + float scale = 2; + float out_scale = 3; + float x_shift = (barbara_width*out_scale - barbara_width*scale) * t; + float y_shift = (barbara_height*out_scale - barbara_height*scale) * t; + + test_subpixel_command(barbara, scale, scale, out_scale, out_scale, x_shift, y_shift); + } + + // Downscaling + for (int i = 0; i <= res; i++) + { + float t = (float)i/res / 2; + test_subpixel_region(barbara, 0.25f, 0.25f, t, t, t+0.5f, t+0.5f); + } + + // No scaling + for (int i = 0; i <= res; i++) + { + float t = (float)i/res / 2; + test_subpixel_region(barbara, 0.5f, 0.5f, t, t, t+0.5f, t+0.5f); + } + + // Upscaling + for (int i = 0; i <= res; i++) + { + float t = (float)i/res / 2; + test_subpixel_region(barbara, 1, 1, t, t, t+0.5f, t+0.5f); + } + for (i = 0; i < 10; i++) test_subpixel(barbara, 0.5f, 0.5f, (float)i / 10, 1); From 831b2d2fa63ee50ceee2d7d59c2face439f17670 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Tue, 10 Nov 2015 13:41:53 -0800 Subject: [PATCH 172/522] Fix a merge gone wrong, add some more test cases. --- stb_image_resize.h | 16 ++++++++-------- tests/resample_test.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 518380b..f7ce8f1 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1004,31 +1004,31 @@ stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) } // What input pixels contribute to this output pixel? -static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float in_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) { float out_pixel_center = (float)n + 0.5f; float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; - float in_pixel_influence_lowerbound = out_pixel_influence_lowerbound / scale_ratio + in_shift; - float in_pixel_influence_upperbound = out_pixel_influence_upperbound / scale_ratio + in_shift; + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; - *in_center_of_out = out_pixel_center / scale_ratio + in_shift; + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); } // What output pixels does this input pixel contribute to? -static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float in_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) { float in_pixel_center = (float)n + 0.5f; float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; - float out_pixel_influence_lowerbound = (in_pixel_influence_lowerbound - in_shift) * scale_ratio; - float out_pixel_influence_upperbound = (in_pixel_influence_upperbound - in_shift) * scale_ratio; + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; - *out_center_of_in = (in_pixel_center - in_shift) * scale_ratio; + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); } diff --git a/tests/resample_test.cpp b/tests/resample_test.cpp index 86b7e5d..e04962b 100644 --- a/tests/resample_test.cpp +++ b/tests/resample_test.cpp @@ -510,6 +510,18 @@ void test_subpixel_1() STBIR_ASSERT(output_data[y * 16 + x + 8] == output_right[y * 8 + x]); } } + + stbir_resize_subpixel(image, 8, 8, 0, output_left, 8, 16, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, 2, 2, 0, 0); + stbir_resize_subpixel(image, 8, 8, 0, output_right, 8, 16, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, 2, 2, 8, 0); + + for (int x = 0; x < 8; x++) + { + for (int y = 0; y < 16; y++) + { + STBIR_ASSERT(output_data[y * 16 + x] == output_left[y * 8 + x]); + STBIR_ASSERT(output_data[y * 16 + x + 8] == output_right[y * 8 + x]); + } + } } // test that replicating an image and using a subtile of it produces same results as wraparound @@ -547,6 +559,14 @@ void test_subpixel_2() for (int y = 0; y < 16; y++) STBIR_ASSERT(output_data_1[y * 16 + x] == output_data_2[y * 16 + x]); }} + + stbir_resize_subpixel(large_image, 32, 32, 0, output_data_2, 16, 16, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_WRAP, STBIR_EDGE_WRAP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, 2, 2, 16, 16); + + {for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + STBIR_ASSERT(output_data_1[y * 16 + x] == output_data_2[y * 16 + x]); + }} } // test that 0,0,1,1 subpixel produces same result as no-rect @@ -570,6 +590,14 @@ void test_subpixel_3() for (int y = 0; y < 32; y++) STBIR_ASSERT(output_data_1[y * 32 + x] == output_data_2[y * 32 + x]); } + + stbir_resize_subpixel(image, 8, 8, 0, output_data_1, 32, 32, 0, STBIR_TYPE_UINT8, 1, 0, STBIR_ALPHA_CHANNEL_NONE, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_LINEAR, NULL, 4, 4, 0, 0); + + for (int x = 0; x < 32; x++) + { + for (int y = 0; y < 32; y++) + STBIR_ASSERT(output_data_1[y * 32 + x] == output_data_2[y * 32 + x]); + } } // test that 1:1 resample using s,t=0,0,1,1 with bilinear produces original image @@ -586,6 +614,9 @@ void test_subpixel_4() stbir_resize_region(image, 8, 8, 0, output, 8, 8, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_TRIANGLE, STBIR_FILTER_TRIANGLE, STBIR_COLORSPACE_LINEAR, &g_context, 0, 0, 1, 1); STBIR_ASSERT(memcmp(image, output, 8 * 8) == 0); + + stbir_resize_subpixel(image, 8, 8, 0, output, 8, 8, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_TRIANGLE, STBIR_FILTER_TRIANGLE, STBIR_COLORSPACE_LINEAR, &g_context, 1, 1, 0, 0); + STBIR_ASSERT(memcmp(image, output, 8 * 8) == 0); } static unsigned int image88_int[8][8]; From 4e691f5917140f9dc6d01974a8195cd8b2edc823 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 12 Nov 2015 06:12:06 -0800 Subject: [PATCH 173/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 96651bd..49ad9b2 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -52,6 +52,7 @@ this! But you might like them anyway: - **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) - **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) - **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) +- _**geometry** [PolyPartition](https://github.com/ivanfratric/polypartition): polygon triangulation, partitioning (MIT license)_ - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) - **network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2) From 5809508de3329c992d4d8dea03a8be7e1a0d0f35 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 12 Nov 2015 06:12:24 -0800 Subject: [PATCH 174/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 49ad9b2..a5c944c 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -17,7 +17,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) -- _**misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) +- _**misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain)_ - _**hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain)_ Not public domain: From 4337345c5ddd636bcdee65439e5a9f4451114e88 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sat, 14 Nov 2015 13:14:26 +0100 Subject: [PATCH 175/522] Prevent HDR info function from trashing stbi context by over-reading --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 0a9de39..a91952b 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6017,7 +6017,7 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) char *token; int valid = 0; - if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) { + if (stbi__hdr_test(s) == 0) { stbi__rewind( s ); return 0; } From 63849198b9ba4a6b464edb70527058a53865a302 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 21 Nov 2015 03:22:21 -0800 Subject: [PATCH 176/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index a5c944c..a9b9d0e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -35,7 +35,7 @@ Not public domain: - **multithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license) -- _**parsing** [zange](https://github.com/vurtun/zange): JSON parser (MIT license)_ +- _**parsing** [mm_json](https://github.com/vurtun/mmx): JSON parser (zlib license)_ - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) From 657eda21550bda493439f153730e4a00334e31ec Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 21 Nov 2015 03:29:15 -0800 Subject: [PATCH 177/522] Update other_libs.md --- docs/other_libs.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index a9b9d0e..3b90230 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -11,14 +11,14 @@ free to tell me about their quality.) _Newest additions are in italics._ - **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) - **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) - **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) -- _**geometry** [sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain)_ +- **geometry** [sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain) - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) -- _**misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain)_ -- _**hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain)_ +- **misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) +- **hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain) Not public domain: @@ -27,19 +27,21 @@ Not public domain: - **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) - **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) +- _**math** [mm_vec.h](https://github.com/vurtun/mmx): vector math (BSD license)_ - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) -- _**network** [wby](https://github.com/vurtun/wby): lightweight webserver, fork of webby (BSD license)_ +- **network** [mm_web.h](https://github.com/vurtun/mmx): lightweight webserver, fork of webby (BSD license) - **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) -- **multithreading** [mts](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) +- **multithreading** [mm_sched.h](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license) -- _**parsing** [mm_json](https://github.com/vurtun/mmx): JSON parser (zlib license)_ +- _**parsing** [mm_json.h](https://github.com/vurtun/mmx): JSON parser (zlib license)_ +- _**parsing** [mm_lexer.h](https://github.com/vurtun/mmx): C-esque language lexer (zlib license)_ - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) -- _**misc** [lualite](https://github.com/janezz55/lualite/): generate lua bindings in C++ (MIT license)_ +- **misc** [lualite](https://github.com/janezz55/lualite/): generate lua bindings in C++ (MIT license) There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone @@ -52,11 +54,11 @@ this! But you might like them anyway: - **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) - **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) - **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) -- _**geometry** [PolyPartition](https://github.com/ivanfratric/polypartition): polygon triangulation, partitioning (MIT license)_ +- **geometry** [PolyPartition](https://github.com/ivanfratric/polypartition): polygon triangulation, partitioning (MIT license) - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) - **network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2) -- _**crypto** [TweetNaCl](http://tweetnacl.cr.yp.to/software.html): high-quality tiny cryptography library (public domain)_ +- **crypto** [TweetNaCl](http://tweetnacl.cr.yp.to/software.html): high-quality tiny cryptography library (public domain) - **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) - **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) @@ -65,16 +67,16 @@ this! But you might like them anyway: - **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) - **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* - **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- _**parsing** [jzon.h](https://github.com/Zguy/Jzon): JSON parser, C++ (MIT license)_ +- **parsing** [jzon.h](https://github.com/Zguy/Jzon): JSON parser, C++ (MIT license) - **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) - **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) -- _**data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license)_ -- _**data structures** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license)_ +- **data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license) +- **data structures** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license) - **data structures**; **algorithms** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain) - **files & filenames** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) - **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license) -- _**misc** [stmr](https://github.com/wooorm/stmr.c): extract English word stems (MIT license)_ -- _**misc** [levenshtein](https://github.com/wooorm/levenshtein.c): compute edit distance between two strings (MIT license)_ +- **misc** [stmr](https://github.com/wooorm/stmr.c): extract English word stems (MIT license) +- **misc** [levenshtein](https://github.com/wooorm/levenshtein.c): compute edit distance between two strings (MIT license) - **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) There is also these XML libraries, but if you're using XML, shame on you: From 2161d1e12a411e74b6893a262f7cf9025cb0d737 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 30 Nov 2015 01:01:28 -0800 Subject: [PATCH 178/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 3b90230..781c2a2 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -15,6 +15,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) +- _**strings** [strpool.h](https://github.com/mattiasgustavsson/libs): string interning (public domain/MIT) - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) - **misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) From 64fa9a3d95efdea727cef159fb6768c046d0a3ba Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 30 Nov 2015 01:01:42 -0800 Subject: [PATCH 179/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 781c2a2..e00f37f 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -15,7 +15,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) -- _**strings** [strpool.h](https://github.com/mattiasgustavsson/libs): string interning (public domain/MIT) +- _**strings** [strpool.h](https://github.com/mattiasgustavsson/libs): string interning (public domain/MIT)_ - **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) - **misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) From cbfa0c44184748728a600fd69e14c5937497618c Mon Sep 17 00:00:00 2001 From: blackpawn Date: Wed, 2 Dec 2015 01:16:29 -0600 Subject: [PATCH 180/522] Fix stb_arr_insertn and stb_arr_deleten memmove lengths They were moving memory beyond the array bounds. --- stb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb.h b/stb.h index d8aaf37..2d9dab6 100644 --- a/stb.h +++ b/stb.h @@ -3249,7 +3249,7 @@ void stb__arr_insertn_(void **pp, int size, int i, int n STB__PARAMS) z = stb_arr_len2(p); stb__arr_addlen_(&p, size, i STB__ARGS); - memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-i)); + memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-(i+n))); } *pp = p; } @@ -3258,7 +3258,7 @@ void stb__arr_deleten_(void **pp, int size, int i, int n STB__PARAMS) { void *p = *pp; if (n) { - memmove((char *) p + i*size, (char *) p + (i+n)*size, size * (stb_arr_len2(p)-i)); + memmove((char *) p + i*size, (char *) p + (i+n)*size, size * (stb_arr_len2(p)-(i+n))); stb_arrhead2(p)->len -= n; } *pp = p; From 28f1b0f5698fe4e05410250895ee7f75d0db4559 Mon Sep 17 00:00:00 2001 From: blackpawn Date: Wed, 2 Dec 2015 22:34:04 -0600 Subject: [PATCH 181/522] Fix for stb_arr_insert --- stb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb.h b/stb.h index 2d9dab6..15ecf51 100644 --- a/stb.h +++ b/stb.h @@ -3062,7 +3062,7 @@ typedef struct #define stb_arr_insertn(a,i,n) (stb__arr_insertn((void **) &(a), sizeof(*a), i, n)) // insert an element at i -#define stb_arr_insert(a,i,v) (stb__arr_insertn((void **) &(a), sizeof(*a), i, n), ((a)[i] = v)) +#define stb_arr_insert(a,i,v) (stb__arr_insertn((void **) &(a), sizeof(*a), i, 1), ((a)[i] = v)) // delete N elements from the middle starting at index 'i' #define stb_arr_deleten(a,i,n) (stb__arr_deleten((void **) &(a), sizeof(*a), i, n)) From a4ab8c08eb4bd74dc22d98e0b1bb70372121fa36 Mon Sep 17 00:00:00 2001 From: blackpawn Date: Wed, 2 Dec 2015 23:12:12 -0600 Subject: [PATCH 182/522] Corrected fix for stb_insertn On insert the memmove length wasn't incorrect but the addlen call was. --- stb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb.h b/stb.h index 15ecf51..eb2b7f6 100644 --- a/stb.h +++ b/stb.h @@ -3248,8 +3248,8 @@ void stb__arr_insertn_(void **pp, int size, int i, int n STB__PARAMS) } z = stb_arr_len2(p); - stb__arr_addlen_(&p, size, i STB__ARGS); - memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-(i+n))); + stb__arr_addlen_(&p, size, n STB__ARGS); + memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-i)); } *pp = p; } From 7453e1bfa417453db9b57091b71ad428ba0a6462 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sat, 5 Dec 2015 23:23:12 +0100 Subject: [PATCH 183/522] stb_image.h: Support 15/16bit per pixel RGB(A) TGAs stbi__tga_* assumed that 16bit TGAs were Grayscale + Alpha. However, if the TGA imagetype is not one of the gray ones, it's 16Bit RGB data, with 5 Bits per channel. If the TGA image descriptor field has alpha bits (the 3 least significant ones) set, the pixel's most significant bit is for alpha: 1 for opaque and 0 for translucent. Furthermore people claim that TGAs can also pretend to have 15bpp, which is the same as 16bpp but definitely without alpha. So 15/16bpp TGAs are now decoded to STBI_rgb(_alpha). --- stb_image.h | 68 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/stb_image.h b/stb_image.h index 0a9de39..82a0ad8 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4813,7 +4813,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int #ifndef STBI_NO_TGA static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) { - int tga_w, tga_h, tga_comp; + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel; int sz; stbi__get8(s); // discard Offset sz = stbi__get8(s); // color type @@ -4824,6 +4824,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) sz = stbi__get8(s); // image type // only RGB or grey allowed, +/- RLE if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; + tga_image_type = sz; stbi__skip(s,9); tga_w = stbi__get16le(s); if( tga_w < 1 ) { @@ -4835,16 +4836,24 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) stbi__rewind(s); return 0; // test height } - sz = stbi__get8(s); // bits per pixel - // only RGB or RGBA or grey allowed - if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) { - stbi__rewind(s); - return 0; + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + sz = stbi__get8(s) & 15; // alpha bits + // only RGB or RGBA (incl. 16bit) or grey allowed + // FIXME: don't we have to use the colormap's bpp if indexed? + switch(tga_bits_per_pixel) { + case 8: tga_comp = STBI_grey; break; + case 15: tga_comp = STBI_rgb; break; + case 16: + if((tga_image_type == 3) || (tga_image_type == 11)) tga_comp = STBI_grey_alpha; + else tga_comp = sz ? STBI_rgb_alpha : STBI_rgb; // most signif. bit might be for alpha + break; + case 24: // fall-through + case 32: tga_comp = tga_bits_per_pixel/8; break; + default: stbi__rewind(s); return 0; } - tga_comp = sz; if (x) *x = tga_w; if (y) *y = tga_h; - if (comp) *comp = tga_comp / 8; + if (comp) *comp = tga_comp; return 1; // seems to have passed everything } @@ -4865,7 +4874,7 @@ static int stbi__tga_test(stbi__context *s) if ( stbi__get16be(s) < 1 ) return 0; // test width if ( stbi__get16be(s) < 1 ) return 0; // test height sz = stbi__get8(s); // bits per pixel - if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) res = 0; else res = 1; @@ -4888,8 +4897,9 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int int tga_width = stbi__get16le(s); int tga_height = stbi__get16le(s); int tga_bits_per_pixel = stbi__get8(s); - int tga_comp = tga_bits_per_pixel / 8; + int tga_comp, tga_rgb16=0; int tga_inverted = stbi__get8(s); + int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits // image data unsigned char *tga_data; unsigned char *tga_palette = NULL; @@ -4905,14 +4915,13 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int tga_image_type -= 8; tga_is_RLE = 1; } - /* int tga_alpha_bits = tga_inverted & 15; */ tga_inverted = 1 - ((tga_inverted >> 5) & 1); // error check if ( //(tga_indexed) || (tga_width < 1) || (tga_height < 1) || (tga_image_type < 1) || (tga_image_type > 3) || - ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && + ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 15) && (tga_bits_per_pixel != 16) && (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) ) { @@ -4924,6 +4933,17 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int { tga_comp = tga_palette_bits / 8; } + else { + switch(tga_bits_per_pixel) { + case 8: tga_comp = STBI_grey; break; + case 15: tga_comp = STBI_rgb; tga_rgb16=1; break; + case 16: + if (tga_image_type == 3) tga_comp = STBI_grey_alpha; + else { tga_comp = tga_alpha_bits ? STBI_rgb_alpha : STBI_rgb; tga_rgb16=1; } + break; + default: tga_comp = tga_bits_per_pixel / 8; // incl. 24 and 32 + } + } // tga info *x = tga_width; @@ -4936,7 +4956,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int // skip to the data's starting position (offset usually = 0) stbi__skip(s, tga_offset ); - if ( !tga_indexed && !tga_is_RLE) { + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { for (i=0; i < tga_height; ++i) { int row = tga_inverted ? tga_height -i - 1 : i; stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; @@ -4999,8 +5019,24 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int { raw_data[j] = tga_palette[pal_idx+j]; } - } else - { + } else if(tga_rgb16) { + // convert from 16bit RGB(A) to 24/32bit RGB(A) + stbi__uint16 px = stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + raw_data[0] = (r * 255)/31; + raw_data[1] = (g * 255)/31; + raw_data[2] = (b * 255)/31; + + if(tga_comp == STBI_rgb_alpha) { + // most significant bit set to 1 for opaque, 0 for trans., according to + // http://www.imagemagick.org/discourse-server/viewtopic.php?t=27469 + raw_data[3] = !(px & 0x8000) * 255; + } + } else { // read in the data raw for (j = 0; j*8 < tga_bits_per_pixel; ++j) { @@ -5043,7 +5079,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int } // swap RGB - if (tga_comp >= 3) + if (tga_comp >= 3 && !tga_rgb16) { unsigned char* tga_pixel = tga_data; for (i=0; i < tga_width * tga_height; ++i) From 57409c3d159af0bb72dac2411fa3183d39202674 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sun, 6 Dec 2015 00:30:16 +0100 Subject: [PATCH 184/522] stb_image.h: Improve stbi__tga_info() and stbi__tga_test() * for paletted images, .._info()'s comp should be based on the palette's bits per pixel, not the images bits per pixel (which describes the size of an index into the palette and is also checked now) * make sure the color (map) type and the image type fields of the header are consistent (=> if TGA color type is 1 for paletted, the TGA image type must be 1 or 9) * .._test() does some more checks and uses stbi__get16le() instead of stbi__get16be() - TGA is little endian. * .._test() now always rewinds (sometimes it used to do only return 0; without rewinding) * remove "error check" at the beginning of stbi__tga_load(), because all that is already tested in stbi__tga_test() --- stb_image.h | 94 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/stb_image.h b/stb_image.h index 82a0ad8..f627fc0 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4813,19 +4813,36 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int #ifndef STBI_NO_TGA static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) { - int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel; - int sz; + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; stbi__get8(s); // discard Offset - sz = stbi__get8(s); // color type - if( sz > 1 ) { + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { stbi__rewind(s); return 0; // only RGB or indexed allowed } - sz = stbi__get8(s); // image type - // only RGB or grey allowed, +/- RLE - if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; - tga_image_type = sz; - stbi__skip(s,9); + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } tga_w = stbi__get16le(s); if( tga_w < 1 ) { stbi__rewind(s); @@ -4837,9 +4854,17 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) return 0; // test height } tga_bits_per_pixel = stbi__get8(s); // bits per pixel + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_bits_per_pixel = tga_colormap_bpp; // make sure colormap's bpp are tested for tga_comp + } sz = stbi__get8(s) & 15; // alpha bits // only RGB or RGBA (incl. 16bit) or grey allowed - // FIXME: don't we have to use the colormap's bpp if indexed? switch(tga_bits_per_pixel) { case 8: tga_comp = STBI_grey; break; case 15: tga_comp = STBI_rgb; break; @@ -4859,25 +4884,31 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) static int stbi__tga_test(stbi__context *s) { - int res; - int sz; + int res = 0; + int sz, tga_color_type; stbi__get8(s); // discard Offset - sz = stbi__get8(s); // color type - if ( sz > 1 ) return 0; // only RGB or indexed allowed + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed sz = stbi__get8(s); // image type - if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE - stbi__get16be(s); // discard palette start - stbi__get16be(s); // discard palette length - stbi__get8(s); // discard bits per palette color entry - stbi__get16be(s); // discard x origin - stbi__get16be(s); // discard y origin - if ( stbi__get16be(s) < 1 ) return 0; // test width - if ( stbi__get16be(s) < 1 ) return 0; // test height + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height sz = stbi__get8(s); // bits per pixel - if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) - res = 0; - else - res = 1; + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: stbi__rewind(s); return res; } @@ -4917,17 +4948,6 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int } tga_inverted = 1 - ((tga_inverted >> 5) & 1); - // error check - if ( //(tga_indexed) || - (tga_width < 1) || (tga_height < 1) || - (tga_image_type < 1) || (tga_image_type > 3) || - ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 15) && (tga_bits_per_pixel != 16) && - (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) - ) - { - return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA - } - // If I'm paletted, then I'll use the number of bits from the palette if ( tga_indexed ) { From d23504932293f7a7b8bb13eae033eff5a03a68df Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sun, 6 Dec 2015 04:33:37 +0100 Subject: [PATCH 185/522] stb_image.h: Fix TGA colormap support * Calculate correct stb format (incl. proper 16bit support) also when using a colormap (palette) * Create colormap with tga_comp, to correctly support 16bit RGB (instead of using tga_palette_bits/8 and just copying the data) * For TGAs with colormap, the TGA bits per pixel field specifies the size of an index to the colormap - the "real" color depth of the image is saved in the color map specification's bits per pixel field. I think only 8 and 16bit indices make sense (16 should be supported, otherwise the colormap length could be u8 instead of u16), so I added support for both. * Helper functions stbi__tga_get_comp() to calculate stb pixelformat and stbi__tga_read_rgb16() to read one 16bit pixel and convert it to 24/32bit RGB(A) - for less duplicate code --- stb_image.h | 134 +++++++++++++++++++++++++++++----------------------- 1 file changed, 74 insertions(+), 60 deletions(-) diff --git a/stb_image.h b/stb_image.h index f627fc0..b0aca9d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4811,6 +4811,26 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int // Targa Truevision - TGA // by Jonathan Dummer #ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int alpha_bits, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if(is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 15: if(is_rgb16) *is_rgb16 = 1; return STBI_rgb; + case 16: + if(is_grey) return STBI_grey_alpha; + else { + if(is_rgb16) *is_rgb16 = 1; + return alpha_bits ? STBI_rgb_alpha : STBI_rgb; // most signif. bit might be for alpha + } + case 24: // fall-through + case 32: return bits_per_pixel/8; + default: return 0; + } +} + static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) { int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; @@ -4854,6 +4874,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) return 0; // test height } tga_bits_per_pixel = stbi__get8(s); // bits per pixel + sz = stbi__get8(s) & 15; // alpha bits if (tga_colormap_bpp != 0) { if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { // when using a colormap, tga_bits_per_pixel is the size of the indexes @@ -4861,20 +4882,13 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) stbi__rewind(s); return 0; } - tga_bits_per_pixel = tga_colormap_bpp; // make sure colormap's bpp are tested for tga_comp + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, sz, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, sz, (tga_image_type == 3) || (tga_image_type == 11), NULL); } - sz = stbi__get8(s) & 15; // alpha bits - // only RGB or RGBA (incl. 16bit) or grey allowed - switch(tga_bits_per_pixel) { - case 8: tga_comp = STBI_grey; break; - case 15: tga_comp = STBI_rgb; break; - case 16: - if((tga_image_type == 3) || (tga_image_type == 11)) tga_comp = STBI_grey_alpha; - else tga_comp = sz ? STBI_rgb_alpha : STBI_rgb; // most signif. bit might be for alpha - break; - case 24: // fall-through - case 32: tga_comp = tga_bits_per_pixel/8; break; - default: stbi__rewind(s); return 0; + if(!tga_comp) { + stbi__rewind(s); + return 0; } if (x) *x = tga_w; if (y) *y = tga_h; @@ -4913,6 +4927,27 @@ errorEnd: return res; } +// read 16bit value and convert to 24/32bit RGB(A) +void stbi__tga_read_rgb16(stbi__context *s, int has_alpha, stbi_uc* out) +{ + stbi__uint16 px = stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (r * 255)/31; + out[1] = (g * 255)/31; + out[2] = (b * 255)/31; + + if(has_alpha) { + // most significant bit set to 1 for opaque, 0 for trans., according to + // http://www.imagemagick.org/discourse-server/viewtopic.php?t=27469 + out[3] = !(px & 0x8000) * 255; + } +} + static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) { // read in the TGA header stuff @@ -4949,21 +4984,11 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int tga_inverted = 1 - ((tga_inverted >> 5) & 1); // If I'm paletted, then I'll use the number of bits from the palette - if ( tga_indexed ) - { - tga_comp = tga_palette_bits / 8; - } - else { - switch(tga_bits_per_pixel) { - case 8: tga_comp = STBI_grey; break; - case 15: tga_comp = STBI_rgb; tga_rgb16=1; break; - case 16: - if (tga_image_type == 3) tga_comp = STBI_grey_alpha; - else { tga_comp = tga_alpha_bits ? STBI_rgb_alpha : STBI_rgb; tga_rgb16=1; } - break; - default: tga_comp = tga_bits_per_pixel / 8; // incl. 24 and 32 - } - } + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, tga_alpha_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, tga_alpha_bits, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); // tga info *x = tga_width; @@ -4989,15 +5014,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int // any data to skip? (offset usually = 0) stbi__skip(s, tga_palette_start ); // load the palette - tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 ); + tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp ); if (!tga_palette) { STBI_FREE(tga_data); return stbi__errpuc("outofmem", "Out of memory"); } - if (!stbi__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { - STBI_FREE(tga_data); - STBI_FREE(tga_palette); - return stbi__errpuc("bad palette", "Corrupt TGA"); + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb || tga_comp == STBI_rgb_alpha); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, tga_comp == STBI_rgb_alpha, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); } } // load the data @@ -5027,39 +5059,21 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int // load however much data we did have if ( tga_indexed ) { - // read in 1 byte, then perform the lookup - int pal_idx = stbi__get8(s); - if ( pal_idx >= tga_palette_len ) - { - // invalid index + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index pal_idx = 0; } - pal_idx *= tga_bits_per_pixel / 8; - for (j = 0; j*8 < tga_bits_per_pixel; ++j) - { + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { raw_data[j] = tga_palette[pal_idx+j]; } } else if(tga_rgb16) { - // convert from 16bit RGB(A) to 24/32bit RGB(A) - stbi__uint16 px = stbi__get16le(s); - stbi__uint16 fiveBitMask = 31; - // we have 3 channels with 5bits each - int r = (px >> 10) & fiveBitMask; - int g = (px >> 5) & fiveBitMask; - int b = px & fiveBitMask; - raw_data[0] = (r * 255)/31; - raw_data[1] = (g * 255)/31; - raw_data[2] = (b * 255)/31; - - if(tga_comp == STBI_rgb_alpha) { - // most significant bit set to 1 for opaque, 0 for trans., according to - // http://www.imagemagick.org/discourse-server/viewtopic.php?t=27469 - raw_data[3] = !(px & 0x8000) * 255; - } + stbi__tga_read_rgb16(s, tga_comp == STBI_rgb_alpha, raw_data); } else { // read in the data raw - for (j = 0; j*8 < tga_bits_per_pixel; ++j) - { + for (j = 0; j < tga_comp; ++j) { raw_data[j] = stbi__get8(s); } } @@ -5098,7 +5112,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int } } - // swap RGB + // swap RGB - if the source data was RGB16, it already is in the right order if (tga_comp >= 3 && !tga_rgb16) { unsigned char* tga_pixel = tga_data; From 87a0396922d2b49ea46d519bd69378761cf9d941 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sun, 6 Dec 2015 05:47:47 +0100 Subject: [PATCH 186/522] stb_image.h: 16 bit TGAs don't really have an alpha channel I claimed that if the most significant bit of a 16bit pixel is set, it should be opaque (as is suggested by some sources on the internet), but implemented the opposite. If implemented "correctly", lots of 16bit TGAs become invisible.. so I guess 16bit TGAs aren't really supposed to have an alpha-channel, or at least most 16bit TGAs (despite having set an "alpha-bit" in the "image descriptor byte") in the wild don't seem to work like that. So just assume 16bit non-greyscale TGAs are always STBI_rgb without an alpha channel. --- stb_image.h | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/stb_image.h b/stb_image.h index b0aca9d..8af5565 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4812,19 +4812,16 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int // by Jonathan Dummer #ifndef STBI_NO_TGA // returns STBI_rgb or whatever, 0 on error -static int stbi__tga_get_comp(int bits_per_pixel, int alpha_bits, int is_grey, int* is_rgb16) +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) { // only RGB or RGBA (incl. 16bit) or grey allowed if(is_rgb16) *is_rgb16 = 0; switch(bits_per_pixel) { case 8: return STBI_grey; - case 15: if(is_rgb16) *is_rgb16 = 1; return STBI_rgb; - case 16: - if(is_grey) return STBI_grey_alpha; - else { - if(is_rgb16) *is_rgb16 = 1; - return alpha_bits ? STBI_rgb_alpha : STBI_rgb; // most signif. bit might be for alpha - } + case 16: if(is_grey) return STBI_grey_alpha; + // else: fall-through + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; case 24: // fall-through case 32: return bits_per_pixel/8; default: return 0; @@ -4874,7 +4871,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) return 0; // test height } tga_bits_per_pixel = stbi__get8(s); // bits per pixel - sz = stbi__get8(s) & 15; // alpha bits + stbi__get8(s); // ignore alpha bits if (tga_colormap_bpp != 0) { if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { // when using a colormap, tga_bits_per_pixel is the size of the indexes @@ -4882,9 +4879,9 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) stbi__rewind(s); return 0; } - tga_comp = stbi__tga_get_comp(tga_colormap_bpp, sz, 0, NULL); + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); } else { - tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, sz, (tga_image_type == 3) || (tga_image_type == 11), NULL); + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); } if(!tga_comp) { stbi__rewind(s); @@ -4927,8 +4924,8 @@ errorEnd: return res; } -// read 16bit value and convert to 24/32bit RGB(A) -void stbi__tga_read_rgb16(stbi__context *s, int has_alpha, stbi_uc* out) +// read 16bit value and convert to 24bit RGB +void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) { stbi__uint16 px = stbi__get16le(s); stbi__uint16 fiveBitMask = 31; @@ -4941,11 +4938,10 @@ void stbi__tga_read_rgb16(stbi__context *s, int has_alpha, stbi_uc* out) out[1] = (g * 255)/31; out[2] = (b * 255)/31; - if(has_alpha) { - // most significant bit set to 1 for opaque, 0 for trans., according to - // http://www.imagemagick.org/discourse-server/viewtopic.php?t=27469 - out[3] = !(px & 0x8000) * 255; - } + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. } static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) @@ -4965,7 +4961,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int int tga_bits_per_pixel = stbi__get8(s); int tga_comp, tga_rgb16=0; int tga_inverted = stbi__get8(s); - int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) // image data unsigned char *tga_data; unsigned char *tga_palette = NULL; @@ -4984,8 +4980,8 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int tga_inverted = 1 - ((tga_inverted >> 5) & 1); // If I'm paletted, then I'll use the number of bits from the palette - if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, tga_alpha_bits, 0, &tga_rgb16); - else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, tga_alpha_bits, (tga_image_type == 3), &tga_rgb16); + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); @@ -5021,9 +5017,9 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int } if (tga_rgb16) { stbi_uc *pal_entry = tga_palette; - STBI_ASSERT(tga_comp == STBI_rgb || tga_comp == STBI_rgb_alpha); + STBI_ASSERT(tga_comp == STBI_rgb); for (i=0; i < tga_palette_len; ++i) { - stbi__tga_read_rgb16(s, tga_comp == STBI_rgb_alpha, pal_entry); + stbi__tga_read_rgb16(s, pal_entry); pal_entry += tga_comp; } } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { @@ -5070,7 +5066,8 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int raw_data[j] = tga_palette[pal_idx+j]; } } else if(tga_rgb16) { - stbi__tga_read_rgb16(s, tga_comp == STBI_rgb_alpha, raw_data); + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); } else { // read in the data raw for (j = 0; j < tga_comp; ++j) { From 9dc860b7ccf9164471b2892a7055dede1ad48279 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 11 Dec 2015 22:55:42 +0000 Subject: [PATCH 187/522] stb_textedit: better support for keying while holding mouse drag button --- stb_textedit.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb_textedit.h b/stb_textedit.h index 6740b91..d1f918f 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -451,6 +451,8 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { int p = stb_text_locate_coord(str, x, y); + if (state->select_start == state->select_end) + state->select_start = state->cursor; state->cursor = state->select_end = p; } From bb39bd44bbf2b028e05d87ff56db2944760515cf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 16 Dec 2015 03:14:03 -0800 Subject: [PATCH 188/522] Update other_libs.md --- docs/other_libs.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index e00f37f..c7e2f5e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -15,8 +15,8 @@ free to tell me about their quality.) _Newest additions are in italics._ - **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) -- _**strings** [strpool.h](https://github.com/mattiasgustavsson/libs): string interning (public domain/MIT)_ -- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) +- **strings** [strpool.h](https://github.com/mattiasgustavsson/libs): string interning (public domain/MIT) +- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallowcate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) - **misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) - **hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain) @@ -28,21 +28,24 @@ Not public domain: - **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) - **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) -- _**math** [mm_vec.h](https://github.com/vurtun/mmx): vector math (BSD license)_ +- **math** [mm_vec.h](https://github.com/vurtun/mmx): vector math (BSD license) - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) +- _**geometry** [par_msquares](https://github.com/prideout/par): convert (binarized) image to triangles (MIT license)_ - **network** [mm_web.h](https://github.com/vurtun/mmx): lightweight webserver, fork of webby (BSD license) +- _**network** [par_easycurl.h](https://github.com/prideout/par): curl wrapper (MIT license)_ - **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) -- **multithreading** [mm_sched.h](https://github.com/vurtun/mts): cross-platform multithreaded task scheduler (zlib license) +- **multithreading** [mm_sched.h](https://github.com/vurtun/mmx): cross-platform multithreaded task scheduler (zlib license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) - **parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license) -- _**parsing** [mm_json.h](https://github.com/vurtun/mmx): JSON parser (zlib license)_ -- _**parsing** [mm_lexer.h](https://github.com/vurtun/mmx): C-esque language lexer (zlib license)_ +- **parsing** [mm_json.h](https://github.com/vurtun/mmx): JSON parser (zlib license) +- **parsing** [mm_lexer.h](https://github.com/vurtun/mmx): C-esque language lexer (zlib license) - **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) - **misc** [lualite](https://github.com/janezz55/lualite/): generate lua bindings in C++ (MIT license) +- _**misc** [tinyformat](https://github.com/c42f/tinyformat): C++ typesafe printf (Boost license)_ There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone From ac8adfdcb3710892809e3d9cbc6998a5ec52818e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 16 Dec 2015 08:22:58 -0800 Subject: [PATCH 189/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index c7e2f5e..9c8bafc 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -16,7 +16,7 @@ free to tell me about their quality.) _Newest additions are in italics._ - **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) - **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) - **strings** [strpool.h](https://github.com/mattiasgustavsson/libs): string interning (public domain/MIT) -- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallowcate small integer IDs efficiently (public domain) +- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) - **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) - **misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) - **hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain) From f5e3afa5c666c570ef9a27f862155c473f272704 Mon Sep 17 00:00:00 2001 From: Sergey Kosarevsky Date: Sun, 3 Jan 2016 02:23:19 +0300 Subject: [PATCH 190/522] Added LUrlParser --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 9c8bafc..bbf790d 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -62,6 +62,7 @@ this! But you might like them anyway: - **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) - **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) - **network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2) +- _**network** [LUrlParser](https://github.com/corporateshark/LUrlParser): lightweight URL & URI parser RFC 1738, RFC 3986 (MIT license)_ - **crypto** [TweetNaCl](http://tweetnacl.cr.yp.to/software.html): high-quality tiny cryptography library (public domain) - **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) - **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) From fc8b6494661167788bd0fef36106f9a492d92704 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 3 Jan 2016 13:38:34 -0800 Subject: [PATCH 191/522] Update other_libs.md --- docs/other_libs.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 9c8bafc..f8e7acf 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -32,9 +32,10 @@ Not public domain: - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) -- _**geometry** [par_msquares](https://github.com/prideout/par): convert (binarized) image to triangles (MIT license)_ +- **geometry** [par_msquares](https://github.com/prideout/par): convert (binarized) image to triangles (MIT license) +- _**geometry** [tk_objfile](https://github.com/joeld42/tk_objfile): OBJ file loader (MIT license)_ - **network** [mm_web.h](https://github.com/vurtun/mmx): lightweight webserver, fork of webby (BSD license) -- _**network** [par_easycurl.h](https://github.com/prideout/par): curl wrapper (MIT license)_ +- **network** [par_easycurl.h](https://github.com/prideout/par): curl wrapper (MIT license) - **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) - **multithreading** [mm_sched.h](https://github.com/vurtun/mmx): cross-platform multithreaded task scheduler (zlib license) - **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) @@ -45,7 +46,7 @@ Not public domain: - **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) - **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) - **misc** [lualite](https://github.com/janezz55/lualite/): generate lua bindings in C++ (MIT license) -- _**misc** [tinyformat](https://github.com/c42f/tinyformat): C++ typesafe printf (Boost license)_ +- **misc** [tinyformat](https://github.com/c42f/tinyformat): C++ typesafe printf (Boost license) There are some that have a source file and require a separate header file (which they may not even supply). That's twice as many files, and we at nothings/stb cannot condone From 5b6d11e9e8b9ffdd4c3468bb003e8ec780142faf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 12 Jan 2016 09:26:10 -0800 Subject: [PATCH 192/522] Update other_libs.md --- docs/other_libs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index f8e7acf..512aa4d 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -33,7 +33,8 @@ Not public domain: - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) - **geometry** [par_msquares](https://github.com/prideout/par): convert (binarized) image to triangles (MIT license) -- _**geometry** [tk_objfile](https://github.com/joeld42/tk_objfile): OBJ file loader (MIT license)_ +- **geometry** [tk_objfile](https://github.com/joeld42/tk_objfile): OBJ file loader (MIT license) +- _**geometry** [par_shapes](http://github.prideout.net/shapes/): generate various 3d geometric shapes (MIT license) - **network** [mm_web.h](https://github.com/vurtun/mmx): lightweight webserver, fork of webby (BSD license) - **network** [par_easycurl.h](https://github.com/prideout/par): curl wrapper (MIT license) - **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) From 1ec8a8c4a44f3d1b0a2e9b06458a6172d5349d7c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 12 Jan 2016 09:26:47 -0800 Subject: [PATCH 193/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 512aa4d..56f19cd 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -34,7 +34,7 @@ Not public domain: - **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) - **geometry** [par_msquares](https://github.com/prideout/par): convert (binarized) image to triangles (MIT license) - **geometry** [tk_objfile](https://github.com/joeld42/tk_objfile): OBJ file loader (MIT license) -- _**geometry** [par_shapes](http://github.prideout.net/shapes/): generate various 3d geometric shapes (MIT license) +- _**geometry** [par_shapes](http://github.prideout.net/shapes/): generate various 3d geometric shapes (MIT license)_ - **network** [mm_web.h](https://github.com/vurtun/mmx): lightweight webserver, fork of webby (BSD license) - **network** [par_easycurl.h](https://github.com/prideout/par): curl wrapper (MIT license) - **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) From 7e741ffc1e78c2ec9dfe8725f8fa52ca8bc393cc Mon Sep 17 00:00:00 2001 From: Romain Bailly Date: Thu, 14 Jan 2016 10:34:30 +0100 Subject: [PATCH 194/522] Added the old size as argument to the STBI_REALLOC() and STBIW_REALLOC() macros --- stb_image.h | 15 ++++++++------- stb_image_write.h | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/stb_image.h b/stb_image.h index 0a9de39..fcb574f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -639,9 +639,9 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #endif #ifndef STBI_MALLOC -#define STBI_MALLOC(sz) malloc(sz) -#define STBI_REALLOC(p,sz) realloc(p,sz) -#define STBI_FREE(p) free(p) +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,oldsz,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) #endif // x86/x64 detection @@ -3616,14 +3616,14 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes { char *q; - int cur, limit; + int cur, limit, old_limit; z->zout = zout; if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); cur = (int) (z->zout - z->zout_start); - limit = (int) (z->zout_end - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); while (cur + n > limit) limit *= 2; - q = (char *) STBI_REALLOC(z->zout_start, limit); + q = (char *) STBI_REALLOC(z->zout_start, old_limit, limit); if (q == NULL) return stbi__err("outofmem", "Out of memory"); z->zout_start = q; z->zout = q + cur; @@ -4408,11 +4408,12 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } if ((int)(ioff + c.length) < (int)ioff) return 0; if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; stbi_uc *p; if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; - p = (stbi_uc *) STBI_REALLOC(z->idata, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + p = (stbi_uc *) STBI_REALLOC(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); z->idata = p; } if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); diff --git a/stb_image_write.h b/stb_image_write.h index 38d3835..c737bb4 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -166,9 +166,9 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, #endif #ifndef STBIW_MALLOC -#define STBIW_MALLOC(sz) malloc(sz) -#define STBIW_REALLOC(p,sz) realloc(p,sz) -#define STBIW_FREE(p) free(p) +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,oldsz,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) #endif #ifndef STBIW_MEMMOVE #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) @@ -647,7 +647,7 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) { int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; - void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); + void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); STBIW_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; From 0860860af60659d5803cbc5ecc6a932029b435c2 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 07:19:27 -0800 Subject: [PATCH 195/522] avoid __forceinline in mingw since their definition for C is broken; dummy definitions for malloc et al (note you have to modify source to make this work though anyway); tweak credits change; --- stb_vorbis.c | 17 +++++++++++++++-- tests/stb.dsp | 4 ++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index ea753df..904209f 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -4,7 +4,7 @@ // Original version written by Sean Barrett in 2007. // // Originally sponsored by RAD Game Tools. Seeking sponsored -// by Phillip Bennefall, Marc Andersen, Elias Software, vgstorm.com, +// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software, // Aras Pranckevicius, and Sean Barrett. // // LICENSE @@ -557,11 +557,24 @@ enum STBVorbisError #endif #else // STB_VORBIS_NO_CRT #define NULL 0 +#define malloc(s) 0 +#define free(s) ((void) 0) +#define realloc(s) 0 #endif // STB_VORBIS_NO_CRT #include -#if !defined(_MSC_VER) && !(defined(__MINGW32__) && defined(__forceinline)) +#ifdef __MINGW32__ + // eff you mingw: + // "fixed": + // http://sourceforge.net/p/mingw-w64/mailman/message/32882927/ + // "no that broke the build, reverted, who cares about C": + // http://sourceforge.net/p/mingw-w64/mailman/message/32890381/ + #ifdef __forceinline + #undef __forceinline + #endif + #define __forceinline +#elif !defined(_MSC_VER) #if __GNUC__ #define __forceinline inline #else diff --git a/tests/stb.dsp b/tests/stb.dsp index b4e1748..3dcb5c9 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -130,6 +130,10 @@ SOURCE=..\stb_leakcheck.h # End Source File # Begin Source File +SOURCE=..\stb_malloc.h +# End Source File +# Begin Source File + SOURCE=..\stb_perlin.h # End Source File # Begin Source File From 95e954c822042edb24d49e836d8ad294edb849fc Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 07:26:16 -0800 Subject: [PATCH 196/522] const correctness for pushdata API; minor tweak to get_samples_interleaved documentation --- stb_vorbis.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 904209f..73dadcf 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -160,10 +160,10 @@ extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); // specification does not bound the size of an individual frame. extern stb_vorbis *stb_vorbis_open_pushdata( - unsigned char *datablock, int datablock_length_in_bytes, + const unsigned char * datablock, int datablock_length_in_bytes, int *datablock_memory_consumed_in_bytes, int *error, - stb_vorbis_alloc *alloc_buffer); + const stb_vorbis_alloc *alloc_buffer); // create a vorbis decoder by passing in the initial data block containing // the ogg&vorbis headers (you don't need to do parse them, just provide // the first N bytes of the file--you're told if it's not enough, see below) @@ -174,7 +174,8 @@ extern stb_vorbis *stb_vorbis_open_pushdata( // incomplete and you need to pass in a larger block from the start of the file extern int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes, + stb_vorbis *f, + const unsigned char *datablock, int datablock_length_in_bytes, int *channels, // place to write number of float * buffers float ***output, // place to write float ** array of float * buffers int *samples // place to write number of output samples @@ -297,15 +298,17 @@ extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***out extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); #endif -// decode the next frame and return the number of samples per channel. the -// data is coerced to the number of channels you request according to the +// decode the next frame and return the number of *samples* per channel. +// Note that for interleaved data, you pass in the number of shorts (the +// size of your array), but the return value is the number of samples per +// channel, not the total number of samples. +// +// The data is coerced to the number of channels you request according to the // channel coercion rules (see below). You must pass in the size of your // buffer(s) so that stb_vorbis will not overwrite the end of the buffer. // The maximum buffer size needed can be gotten from get_info(); however, // the Vorbis I specification implies an absolute maximum of 4096 samples -// per channel. Note that for interleaved data, you pass in the number of -// shorts (the size of your array), but the return value is the number of -// samples per channel, not the total number of samples. +// per channel. // Channel coercion rules: // Let M be the number of channels requested, and N the number of channels present, From 3560e553e89f054a70d46ba447fbe9323600e4c9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 07:42:24 -0800 Subject: [PATCH 197/522] stb_vorbis version history and contributor info --- stb_vorbis.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 3d1b313..eff8c98 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -33,13 +33,10 @@ // Laurent Gomila Marc LeBlanc Ronny Chevalier // Bernhard Wodo Evan Balster "alxprd"@github // Tom Beaumont Ingo Leitgeb Nicolas Guillemot -// Phillip Bennefall -// (If you reported a bug but do not appear in this list, it is because -// someone else reported the bug before you. There were too many of you to -// list them all because I was lax about updating for a long time, sorry.) +// Phillip Bennefall Rohit // // Partial history: -// 1.07 - 2015/11/08 - fixes for crashes on invalid files +// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const // 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) // some crash fixes when out of memory or with corrupt files // fix some inappropriately signed shifts @@ -50,8 +47,6 @@ // 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct) // 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel; // (API change) report sample rate for decode-full-file funcs -// 0.99996 - - bracket #include for macintosh compilation -// 0.99995 - - avoid alias-optimization issue in float-to-int conversion // // See end of file for full version history. @@ -5416,6 +5411,8 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API + some more crash fixes when out of memory or with corrupt files 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) some crash fixes when out of memory or with corrupt files 1.05 - 2015/04/19 - don't define __forceinline if it's redundant From 418d21f2e28cdda9044330827c844dbed89676ee Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 07:52:15 -0800 Subject: [PATCH 198/522] bump the version number and add version hisoty --- stb_c_lexer.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index c1c4279..f6a0035 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -1,4 +1,4 @@ -// stb_c_lexer.h - v0.06 - public domain Sean Barrett 2013 +// stb_c_lexer.h - v0.07 - public domain Sean Barrett 2013 // lexer for making little C-like languages with recursive-descent parsers // // This file provides both the interface and the implementation. @@ -10,6 +10,7 @@ // suffixes on integer constants are not handled (you can override this). // // History: +// 0.07 fix mishandling of hexadecimal constants parsed by strtol // 0.06 fix missing next character after ending quote mark (Andreas Fredriksson) // 0.05 refixed get_location because github version had lost the fix // 0.04 fix octal parsing bug From 1964d53d70507f26a82286208afb5a54a2208392 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 08:01:42 -0800 Subject: [PATCH 199/522] update version number and version history with everything committed to date --- stb_image.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 429f2ff..3a8f3b1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.08 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.09 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -6391,6 +6391,8 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.09 (2016-01-16) allow comments in PNM files + info() for BMP to shares code instead of sloppy parse 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) fix compiler warnings partial animated GIF support From e30b75af8bfe864e77664b3b1e8c22b211f406b1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 08:05:40 -0800 Subject: [PATCH 200/522] update contributor list --- stb_image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_image.h b/stb_image.h index 21c1e29..7c1c91f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -213,6 +213,7 @@ Nathan Reed Michaelangel007@github Nick Verigakis + svdijk@github LICENSE From 9cb29b6b39c1c2cd52843da6fef922852ee020aa Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 08:13:55 -0800 Subject: [PATCH 201/522] update and reorganize contributor list --- stb_image.h | 67 ++++++++++++++++++++++------------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/stb_image.h b/stb_image.h index 56779ad..ebe7f16 100644 --- a/stb_image.h +++ b/stb_image.h @@ -175,45 +175,34 @@ ============================ Contributors ========================= - Image formats Bug fixes & warning fixes - Sean Barrett (jpeg, png, bmp) Marc LeBlanc - Nicolas Schulz (hdr, psd) Christpher Lloyd - Jonathan Dummer (tga) Dave Moore - Jean-Marc Lienher (gif) Won Chun - Tom Seddon (pic) the Horde3D community - Thatcher Ulrich (psd) Janez Zemva - Ken Miller (pgm, ppm) Jonathan Blow - urraka@github (animated gif) Laurent Gomila - Aruelien Pocheville - Ryamond Barbiero - David Woo - Extensions, features Martin Golini - Jetro Lauha (stbi_info) Roy Eltham - Martin "SpartanJ" Golini (stbi_info) Luke Graham - James "moose2000" Brown (iPhone PNG) Thomas Ruf - Ben "Disch" Wenger (io callbacks) John Bartholomew - Omar Cornut (1/2/4-bit PNG) Ken Hamada - Nicolas Guillemot (vertical flip) Cort Stratton - Richard Mitton (16-bit PSD) Blazej Dariusz Roszkowski - Junggon Kim (PNM comments) Thibault Reuille - Paul Du Bois - Guillaume George - Jerry Jansson - Hayaki Saito - Johan Duparc - Ronny Chevalier - Optimizations & bugfixes Michal Cichon - Fabian "ryg" Giesen Tero Hanninen - Arseny Kapoulkine Sergio Gonzalez - Cass Everitt - Engin Manap - If your name should be here but Martins Mozeiko - isn't, let Sean know. Joseph Thomson - Phil Jordan - Nathan Reed - Michaelangel007@github - Nick Verigakis - svdijk@github + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + urraka@github (animated gif) Junggon Kim (PNM comments) + + Optimizations & bugfixes + Fabian "ryg" Giesen + Arseny Kapoulkine + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson + Dave Moore Roy Eltham Hayaki Saito Phil Jordan + Won Chun Luke Graham Johan Duparc Nathan Reed + the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis + Janez Zemva John Bartholomew Michal Cichon svdijk@github + Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson + Laurent Gomila Cort Stratton Sergio Gonzalez + Aruelien Pocheville Thibault Reuille Cass Everitt + Ryamond Barbiero Paul Du Bois Engin Manap + Blazej Dariusz Roszkowski + Michaelangel007@github + LICENSE From c8e50127c553ee578d76797adfca2f7825d25016 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 09:37:34 -0800 Subject: [PATCH 202/522] contributor list --- stb_image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_image.h b/stb_image.h index cb7ff67..6faf88c 100644 --- a/stb_image.h +++ b/stb_image.h @@ -184,6 +184,7 @@ Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) urraka@github (animated gif) Junggon Kim (PNM comments) + Daniel Gibson (16-bit TGA) Optimizations & bugfixes Fabian "ryg" Giesen From 82ca643ef3b1af0840f4069d691e2c2871fc127e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 09:47:22 -0800 Subject: [PATCH 203/522] change previous explicitly-sized realloc support to be new API and unbreak old API --- stb_image.h | 20 ++++++++++++-------- stb_image_write.h | 20 +++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/stb_image.h b/stb_image.h index e2a89ef..7709f6c 100644 --- a/stb_image.h +++ b/stb_image.h @@ -621,18 +621,22 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) #endif -#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC) +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) // ok -#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) // ok #else -#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC." +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." #endif #ifndef STBI_MALLOC -#define STBI_MALLOC(sz) malloc(sz) -#define STBI_REALLOC(p,oldsz,newsz) realloc(p,newsz) -#define STBI_FREE(p) free(p) +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) #endif // x86/x64 detection @@ -3615,7 +3619,7 @@ static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room limit = old_limit = (int) (z->zout_end - z->zout_start); while (cur + n > limit) limit *= 2; - q = (char *) STBI_REALLOC(z->zout_start, old_limit, limit); + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); if (q == NULL) return stbi__err("outofmem", "Out of memory"); z->zout_start = q; z->zout = q + cur; @@ -4405,7 +4409,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; - p = (stbi_uc *) STBI_REALLOC(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); z->idata = p; } if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); diff --git a/stb_image_write.h b/stb_image_write.h index c737bb4..aa4b828 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -157,19 +157,25 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, #include #include -#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC) +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) // ok -#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) // ok #else -#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC." +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." #endif #ifndef STBIW_MALLOC -#define STBIW_MALLOC(sz) malloc(sz) -#define STBIW_REALLOC(p,oldsz,newsz) realloc(p,newsz) -#define STBIW_FREE(p) free(p) +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) #endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + #ifndef STBIW_MEMMOVE #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) #endif @@ -647,7 +653,7 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) { int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; - void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); STBIW_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; From 79f29bafffdbf33cb566102b1635c144beba0f28 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 09:48:01 -0800 Subject: [PATCH 204/522] fix previous stb_vorbis check-in that didn't actually compile; make stb_vorbis_alloc* parameter in APIs be const --- stb_vorbis.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index eff8c98..d54087f 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -234,18 +234,18 @@ extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *chan // When you're done with it, just free() the pointer returned in *output. extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, - int *error, stb_vorbis_alloc *alloc_buffer); + int *error, const stb_vorbis_alloc *alloc_buffer); // create an ogg vorbis decoder from an ogg vorbis stream in memory (note // this must be the entire stream!). on failure, returns NULL and sets *error #ifndef STB_VORBIS_NO_STDIO extern stb_vorbis * stb_vorbis_open_filename(const char *filename, - int *error, stb_vorbis_alloc *alloc_buffer); + int *error, const stb_vorbis_alloc *alloc_buffer); // create an ogg vorbis decoder from a filename via fopen(). on failure, // returns NULL and sets *error (possibly to VORBIS_file_open_failure). extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, - int *error, stb_vorbis_alloc *alloc_buffer); + int *error, const stb_vorbis_alloc *alloc_buffer); // create an ogg vorbis decoder from an open FILE *, looking for a stream at // the _current_ seek point (ftell). on failure, returns NULL and sets *error. // note that stb_vorbis must "own" this stream; if you seek it in between @@ -255,7 +255,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, // function, stb_vorbis_open_file_section(), to limit it. extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, - int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len); + int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len); // create an ogg vorbis decoder from an open FILE *, looking for a stream at // the _current_ seek point (ftell); the stream will be of length 'len' bytes. // on failure, returns NULL and sets *error. note that stb_vorbis must "own" @@ -4235,7 +4235,7 @@ void stb_vorbis_close(stb_vorbis *p) setup_free(p,p); } -static void vorbis_init(stb_vorbis *p, stb_vorbis_alloc *z) +static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z) { memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start if (z) { @@ -4393,11 +4393,11 @@ static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) // return value: number of bytes we used int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, // the file we're decoding - uint8 *data, int data_len, // the memory available for decoding - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples + stb_vorbis *f, // the file we're decoding + const uint8 *data, int data_len, // the memory available for decoding + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples ) { int i; @@ -4407,11 +4407,11 @@ int stb_vorbis_decode_frame_pushdata( if (f->page_crc_tests >= 0) { *samples = 0; - return vorbis_search_for_page_pushdata(f, data, data_len); + return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len); } - f->stream = data; - f->stream_end = data + data_len; + f->stream = (uint8 *) data; + f->stream_end = (uint8 *) data + data_len; f->error = VORBIS__no_error; // check that we have the entire packet in memory @@ -4463,14 +4463,14 @@ int stb_vorbis_decode_frame_pushdata( } stb_vorbis *stb_vorbis_open_pushdata( - unsigned char *data, int data_len, // the memory available for decoding + const unsigned char *data, int data_len, // the memory available for decoding int *data_used, // only defined if result is not NULL - int *error, stb_vorbis_alloc *alloc) + int *error, const stb_vorbis_alloc *alloc) { stb_vorbis *f, p; vorbis_init(&p, alloc); - p.stream = data; - p.stream_end = data + data_len; + p.stream = (uint8 *) data; + p.stream_end = (uint8 *) data + data_len; p.push_mode = TRUE; if (!start_decoder(&p)) { if (p.eof) @@ -4990,7 +4990,7 @@ int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) #ifndef STB_VORBIS_NO_STDIO -stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc, unsigned int length) +stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length) { stb_vorbis *f, p; vorbis_init(&p, alloc); @@ -5011,7 +5011,7 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er return NULL; } -stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc) +stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) { unsigned int len, start; start = ftell(file); @@ -5021,7 +5021,7 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); } -stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorbis_alloc *alloc) +stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) { FILE *f = fopen(filename, "rb"); if (f) @@ -5031,7 +5031,7 @@ stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorb } #endif // STB_VORBIS_NO_STDIO -stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, stb_vorbis_alloc *alloc) +stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) { stb_vorbis *f, p; if (data == NULL) return NULL; From ac748cba9bd9751bd5b219d0eca4c73ca94b583d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 09:57:04 -0800 Subject: [PATCH 205/522] update contributor list, version history, version number --- stb_image.h | 7 +++++-- stb_image_write.h | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 7709f6c..5e07746 100644 --- a/stb_image.h +++ b/stb_image.h @@ -146,6 +146,7 @@ Latest revision history: + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) partial animated GIF support limited 16-bit PSD support @@ -198,7 +199,7 @@ the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis Janez Zemva John Bartholomew Michal Cichon svdijk@github Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson - Laurent Gomila Cort Stratton Sergio Gonzalez + Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github Aruelien Pocheville Thibault Reuille Cass Everitt Ryamond Barbiero Paul Du Bois Engin Manap Blazej Dariusz Roszkowski @@ -6456,11 +6457,13 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) fix compiler warnings partial animated GIF support - limited 16-bit PSD support + limited 16-bpc PSD support #ifdef unused functions bug with < 92 byte PIC,PNM,HDR,TGA 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value diff --git a/stb_image_write.h b/stb_image_write.h index aa4b828..2d1e670 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.00 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.01 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -98,6 +98,7 @@ CREDITS: github:Chribba Guillaume Chereau github:jry2 + github:romigrou LICENSE @@ -974,6 +975,8 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support 1.00 (2015-09-14) installable file IO function 0.99 (2015-09-13) From 472c4c82a44378b64245b1fbeaa9849f2cd0c51b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 10:00:19 -0800 Subject: [PATCH 206/522] update version history --- stb_image.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb_image.h b/stb_image.h index 5e07746..be25097 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6458,8 +6458,10 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int revision history: 2.09 (2016-01-16) allow comments in PNM files 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling info() for BMP to shares code instead of sloppy parse can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) fix compiler warnings partial animated GIF support From 8521c38956577468acc4c942348fb563ee0f2646 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 10:09:35 -0800 Subject: [PATCH 207/522] tweak previous crc commit --- stb_image_write.h | 104 +++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 66 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index c6c604a..d76a616 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -100,6 +100,7 @@ CREDITS: github:jry2 github:romigrou Sergio Gonzalez + Jonas Karlsson LICENSE @@ -827,78 +828,47 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l return (unsigned char *) stbiw__sbraw(out); } -unsigned int stbiw__crc32(unsigned char *buffer, int len) +static unsigned int stbiw__crc32(unsigned char *buffer, int len) { static unsigned int crc_table[256] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; unsigned int crc = ~0u; - for (int i=0; i < len; ++i) + int i; + for (i=0; i < len; ++i) crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; return ~crc; } @@ -1044,6 +1014,8 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, /* Revision history 1.01 (2016-01-16) STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues 1.00 (2015-09-14) installable file IO function 0.99 (2015-09-13) From f1d2002a1db72294478943146052de7fac452327 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 10:16:23 -0800 Subject: [PATCH 208/522] update contributor list --- stb_image_write.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_image_write.h b/stb_image_write.h index 3407ca1..98fa410 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -101,6 +101,7 @@ CREDITS: github:romigrou Sergio Gonzalez Jonas Karlsson + Filip Wasil LICENSE From ad9a570e271a8b00ac9574415feee6cc9dd597fb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 10:20:54 -0800 Subject: [PATCH 209/522] stb_truetype version history; update README --- README.md | 12 ++++++------ stb_truetype.h | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0fb310e..889cbbc 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**stb_vorbis.c** | 1.06 | audio | 5441 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.08 | graphics | 6509 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.08 | graphics | 3235 | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 1.00 | graphics | 993 | image writing to disk: PNG, TGA, BMP +**stb_vorbis.c** | 1.07 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output +**stb_image.h** | 2.09 | graphics | 6610 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_truetype.h** | 1.09 | graphics | 3246 | parse, decode, and rasterize characters from truetype fonts +**stb_image_write.h** | 1.01 | graphics | 1044 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ @@ -21,13 +21,13 @@ library | lastest version | category | LoC | description **stb_easy_font.h** | 0.6 | 3D graphics | 232 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **stb_tilemap_editor.h** | 0.36 | game dev | 4127 | embeddable tilemap editor **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator -**stb_c_lexer.h** | 0.06 | parsing | 815 | simplify writing parsers for C-like languages +**stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" **stb.h** | 2.25 | misc | 14136 | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46448 +Total lines of C code: 46633 FAQ diff --git a/stb_truetype.h b/stb_truetype.h index 0b1e3b5..b112b8a 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -50,7 +50,7 @@ // // VERSION HISTORY // -// 1.09 (????-??-??) warning fix; avoid crash on outofmem +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; @@ -3203,6 +3203,7 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // FULL VERSION HISTORY // +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // allow PackFontRanges to pack and render in separate phases; From 48ec72ac12383a8bbfa567c41b85184b60ad2f4a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jan 2016 10:26:36 -0800 Subject: [PATCH 210/522] Update stbtt_fontinfo.userdata field on paths where user never has access to it. --- stb_truetype.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index b112b8a..bfb1841 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -50,7 +50,7 @@ // // VERSION HISTORY // -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; @@ -2522,6 +2522,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // fo float scale; int x,y,bottom_y, i; stbtt_fontinfo f; + f.userdata = NULL; if (!stbtt_InitFont(&f, data, offset)) return -1; STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels @@ -2986,6 +2987,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd if (rects == NULL) return 0; + info.userdata = spc->user_allocator_context; stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); @@ -3203,7 +3205,7 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // FULL VERSION HISTORY // -// 1.09 (2016-01-16) warning fix; avoid crash on outofmem +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // allow PackFontRanges to pack and render in separate phases; From 4ef7d07a442cb7b3277a3f3405a12042e1feb2c4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 10 Jan 2016 19:58:23 -0700 Subject: [PATCH 211/522] ttf: Correct direct use of fabs() Add a macro to allow fabs() to be provided by the user, as with the other maths functions. Update the implementation code to use it instead of fasb(). Signed-off-by: Simon Glass --- stb_truetype.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 00d22eb..d3ba508 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -403,6 +403,11 @@ int main(int arg, char **argv) #define STBTT_sqrt(x) sqrt(x) #endif + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h #ifndef STBTT_malloc #include @@ -1986,7 +1991,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, } y_crossing += dy * (x2 - (x1+1)); - STBTT_assert(fabs(area) <= 1.01f); + STBTT_assert(STBTT_fabs(area) <= 1.01f); scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); @@ -2120,7 +2125,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int m; sum += scanline2[i]; k = scanline[i] + sum; - k = (float) fabs(k)*255 + 0.5f; + k = (float) STBTT_fabs(k)*255 + 0.5f; m = (int) k; if (m > 255) m = 255; result->pixels[j*result->stride + i] = (unsigned char) m; From 3364990ac3b858c38976bb24dee277a7c61f8ff8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 18 Jan 2016 13:24:17 -0800 Subject: [PATCH 212/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 1d1eda9..687c2a0 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -95,7 +95,7 @@ There are some libraries that are just _so_ awesome that even though they use mo than two files we're going to give them special dispensation to appear in their own little list here. If you're a crazy purist, be warned, but otherwise, enjoy! -- **user interface** [ImGui](https://github.com/ocornut/imgui): an immediate-mode GUI ("imgui") named "ImGui" (MIT license) +- **user interface** [dear imgui](https://github.com/ocornut/imgui): an immediate-mode GUI ("imgui") named "ImGui" (MIT license) Also you might be interested in other related, but different lists: From bc1b1f6cc993d87aff438cfd1fb550a36fe2780d Mon Sep 17 00:00:00 2001 From: Eugene Opalev Date: Mon, 18 Jan 2016 19:38:07 -0800 Subject: [PATCH 213/522] Warning C4703 fix --- stb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb.h b/stb.h index d8aaf37..b152c91 100644 --- a/stb.h +++ b/stb.h @@ -7786,7 +7786,7 @@ stb_ps *stb_ps_remove_any(stb_ps *ps, void **value) void ** stb_ps_getlist(stb_ps *ps, int *count) { int i,n=0; - void **p; + void **p = NULL; switch (3 & (int) ps) { case STB_ps_direct: if (ps == NULL) { *count = 0; return NULL; } From a5bbc93087575e82f927cbf9e9e3e2a5c1e2c4d9 Mon Sep 17 00:00:00 2001 From: Eugene Opalev Date: Mon, 18 Jan 2016 22:41:17 -0800 Subject: [PATCH 214/522] Warning C4005 fix --- stb.h | 6 ++++++ stb_tilemap_editor.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/stb.h b/stb.h index b152c91..818554e 100644 --- a/stb.h +++ b/stb.h @@ -207,9 +207,15 @@ CREDITS #endif #ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NONSTDC_NO_DEPRECATE + #endif + #ifndef _CRT_NON_CONFORMING_SWPRINTFS #define _CRT_NON_CONFORMING_SWPRINTFS + #endif #if !defined(_MSC_VER) || _MSC_VER > 1700 #include // _BitScanReverse #endif diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 64480ba..f1f8155 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -328,7 +328,9 @@ #define STB_TILEMAP_INCLUDE_STB_TILEMAP_EDITOR_H #ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS + #endif #include #include #endif From 8f9be5adfc6e948dae79303dfab8fcd642658c39 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 21 Jan 2016 06:35:48 -0800 Subject: [PATCH 215/522] Update other_libs.md --- docs/other_libs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 687c2a0..1162f3b 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -29,12 +29,13 @@ Not public domain: - **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) - **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) - **math** [mm_vec.h](https://github.com/vurtun/mmx): vector math (BSD license) +- _**math** [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs): approximate transcendental functions optimized for shaders (esp. GCN) (MIT license)_ - **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) - **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) - **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) - **geometry** [par_msquares](https://github.com/prideout/par): convert (binarized) image to triangles (MIT license) - **geometry** [tk_objfile](https://github.com/joeld42/tk_objfile): OBJ file loader (MIT license) -- _**geometry** [par_shapes](http://github.prideout.net/shapes/): generate various 3d geometric shapes (MIT license)_ +- **geometry** [par_shapes](http://github.prideout.net/shapes/): generate various 3d geometric shapes (MIT license) - **network** [mm_web.h](https://github.com/vurtun/mmx): lightweight webserver, fork of webby (BSD license) - **network** [par_easycurl.h](https://github.com/prideout/par): curl wrapper (MIT license) - **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) From 30015ef46442b58d42f223d8a4fbc42a961a7afe Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 04:06:28 -0800 Subject: [PATCH 216/522] attempt to fix unused var warnings in stb_image 2.09 --- stb_image.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index be25097..e06f7a1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.09 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.10 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -146,6 +146,7 @@ Latest revision history: + 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) partial animated GIF support @@ -3621,6 +3622,7 @@ static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room while (cur + n > limit) limit *= 2; q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); if (q == NULL) return stbi__err("outofmem", "Out of memory"); z->zout_start = q; z->zout = q + cur; @@ -4410,6 +4412,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); z->idata = p; } @@ -6456,6 +6459,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED 2.09 (2016-01-16) allow comments in PNM files 16-bit-per-pixel TGA (not bit-per-component) info() for TGA could break due to .hdr handling From 8b144eb536598ea51310be0c3c97523fd5b79d49 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 04:27:47 -0800 Subject: [PATCH 217/522] stb_easy_font: support '\n' in _width(), add _height() [untested] --- stb_easy_font.h | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/stb_easy_font.h b/stb_easy_font.h index 4dee383..2fad91f 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -1,4 +1,4 @@ -// stb_easy_font.h - v0.6 - bitmap font for 3D rendering - public domain +// stb_easy_font.h - v0.7 - bitmap font for 3D rendering - public domain // Sean Barrett, Feb 2015 // // Easy-to-deploy, @@ -16,8 +16,10 @@ // DOCUMENTATION: // // int stb_easy_font_width(char *text) +// int stb_easy_font_height(char *text) // -// Takes a string without newlines and returns the horizontal size. +// Takes a string and returns the horizontal size and the +// vertical size (which can vary if 'text' has newlines). // // int stb_easy_font_print(float x, float y, // char *text, unsigned char color[4], @@ -40,7 +42,7 @@ // // You can ignore z and color if you get them from elsewhere // This format was chosen in the hopes it would make it -// easier for you to reuse existing buffer-drawing code. +// easier for you to reuse existing vertex-buffer-drawing code. // // If you pass in NULL for color, it becomes 255,255,255,255. // @@ -63,11 +65,6 @@ // compact to me; -0.5 is a reasonable compromise as long as // you're scaling the font up. // -// SAMPLE CODE: -// -// Here's sample code for old OpenGL; it's a lot more complicated -// to make work on modern APIs, and that's your problem. -// // LICENSE // // This software is in the public domain. Where that dedication is not @@ -76,10 +73,16 @@ // // VERSION HISTORY // +// (2016-01-22) 0.7 width() supports multiline text; add height() // (2015-09-13) 0.6 #include ; updated license // (2015-02-01) 0.5 First release #if 0 +// SAMPLE CODE: +// +// Here's sample code for old OpenGL; it's a lot more complicated +// to make work on modern APIs, and that's your problem. +// void print_string(float x, float y, char *text, float r, float g, float b) { static char buffer[99999]; // ~500 chars @@ -222,11 +225,34 @@ static int stb_easy_font_print(float x, float y, char *text, unsigned char color static int stb_easy_font_width(char *text) { float len = 0; + float max_len = 0; while (*text) { - len += stb_easy_font_charinfo[*text-32].advance & 15; - len += stb_easy_font_spacing_val; + if (*text == '\n') { + if (len > max_len) max_len = len; + len = 0; + } else { + len += stb_easy_font_charinfo[*text-32].advance & 15; + len += stb_easy_font_spacing_val; + } ++text; } - return (int) ceil(len); + if (len > max_len) max_len = len; + return (int) ceil(max_len); +} + +static int stb_easy_font_height(char *text) +{ + float y = 0; + int nonempty_line=0; + while (*text) { + if (*text == '\n') { + y += 12; + nonempty_line = 0; + } else { + nonempty_line = 1; + } + ++text; + } + return (int) ceil(y + (nonempty_line ? 12 : 0)); } #endif From 820f63be441101bbb255d5b583a1495a0884c91a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 05:17:12 -0800 Subject: [PATCH 218/522] stb_tilemap_editor: fix typo in docuemtnation, update version & credits --- stb.h | 6 +++++- stb_tilemap_editor.h | 6 ++++-- tests/stb.dsp | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/stb.h b/stb.h index cd86718..4b28ae1 100644 --- a/stb.h +++ b/stb.h @@ -1,4 +1,4 @@ -/* stb.h - v2.25 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h +/* stb.h - v2.26 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h no warranty is offered or implied; use this code at your own risk This is a single header file with a bunch of useful utilities @@ -25,6 +25,7 @@ Version History + 2.26 various warning & buffixes 2.25 various warning & bugfixes 2.24 various warning & bugfixes 2.23 fix 2.22 @@ -186,6 +187,9 @@ CREDITS Mojofreem@github Ryan Whitworth Vincent Isambart + Mike Sartain + Eugene Opalev + Tim Sjostrand */ #ifndef STB__INCLUDE_STB_H diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index f1f8155..b244c9d 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1,4 +1,4 @@ -// stb_tilemap_editor.h - v0.36 - Sean Barrett - http://nothings.org/stb +// stb_tilemap_editor.h - v0.37 - Sean Barrett - http://nothings.org/stb // placed in the public domain - not copyrighted - first released 2014-09 // // Embeddable tilemap editor for C/C++ @@ -259,7 +259,7 @@ // #define STBTE_MAX_CATEGORIES 100 // #define STBTE_UNDO_BUFFER_BYTES (1 << 24) // 16 MB // #define STBTE_MAX_COPY 90000 // e.g. 300x300 -// #define STBTE_MAX_PROPERTIESERTIES 10 // max properties per tile +// #define STBTE_MAX_PROPERTIES 10 // max properties per tile // // API // @@ -275,6 +275,7 @@ // either approach allows cut&pasting between levels.) // // REVISION HISTORY +// 0.37 fix warning // 0.36 minor compiler support // 0.35 layername button changes // - layername buttons grow with the layer panel @@ -311,6 +312,7 @@ // Josh Huelsman // Bugfixes: // Ryan Whitworth +// Eugene Opalev // // LICENSE // diff --git a/tests/stb.dsp b/tests/stb.dsp index 3dcb5c9..20f341b 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # 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 /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "VORBIS_TEST" /FR /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "MAIN_TEST" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" From bb5917fa9362bf01de14c0865266345b1d549cb3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 06:58:57 -0800 Subject: [PATCH 219/522] update readme --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 889cbbc..a5fdd4a 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **stb_vorbis.c** | 1.07 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.09 | graphics | 6610 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.09 | graphics | 3246 | parse, decode, and rasterize characters from truetype fonts +**stb_image.h** | 2.10 | graphics | 6614 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_truetype.h** | 1.09 | graphics | 3249 | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 1.01 | graphics | 1044 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality @@ -18,16 +18,16 @@ library | lastest version | category | LoC | description **stb_voxel_render.h** | 0.83 | 3D graphics | 3750 | Minecraft-esque voxel rendering "engine" with many more features **stb_dxt.h** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **stb_perlin.h** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) -**stb_easy_font.h** | 0.6 | 3D graphics | 232 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc -**stb_tilemap_editor.h** | 0.36 | game dev | 4127 | embeddable tilemap editor +**stb_easy_font.h** | 0.7 | 3D graphics | 258 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc +**stb_tilemap_editor.h** | 0.37 | game dev | 4131 | embeddable tilemap editor **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**stb.h** | 2.25 | misc | 14136 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**stb.h** | 2.26 | misc | 14184 | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46633 +Total lines of C code: 46718 FAQ From b9a29d9b5be7a6d5c6d8253c06317c5baa2fb727 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 06:59:09 -0800 Subject: [PATCH 220/522] reorganize other_libs by category --- docs/other_libs.md | 165 ++++++++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 83 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 1162f3b..0e98907 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -4,100 +4,99 @@ In addition to all of [my libraries](https://github.com/nothings/stb), there are People have told me about quite a few of these. However, I haven't used most of these libraries and can't comment on their quality. (If you use them and aren't their author, feel -free to tell me about their quality.) _Newest additions are in italics._ +free to tell me about their quality. -- **images** [jo_gif.cpp](http://www.jonolick.com/home/gif-writer): animated GIF writer (public domain) -- **images** [gif.h](https://github.com/ginsweater/gif-h): animated GIF writer (public domain) -- **images** [tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h): JPEG encoder (public domain) -- **images** [miniexr](https://github.com/aras-p/miniexr): OpenEXR writer (public domain) -- **geometry** [nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/): find voronoi regions on lattice w/ integer inputs (public domain) -- **geometry** [sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h): sobol & stratified sampling sequences (public domain) -- **network** [zed_net](https://github.com/ZedZull/zed_net): cross-platform socket wrapper (public domain) -- **strings**; **files & filenames** [DG_misc.h](https://github.com/DanielGibson/Snippets/): Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings (public domain) -- **strings** [utf8](https://github.com/sheredom/utf8.h): utf8 string library (public domain) -- **strings** [strpool.h](https://github.com/mattiasgustavsson/libs): string interning (public domain/MIT) -- **misc** [MakeID.h](http://www.humus.name/3D/MakeID.h): allocate/deallocate small integer IDs efficiently (public domain) -- **misc** [gb_string.h](https://github.com/gingerBill/gb): dynamic strings for C (public domain) -- **misc** [loguru](https://github.com/emilk/loguru): flexible logging for C++ (public domain) -- **hardware** [EasyTab](https://github.com/ApoorvaJ/EasyTab): multi-platform tablet input (public domain) +**Public domain single-file libraries are in bold.** -Not public domain: -- **images** [tinyexr](https://github.com/syoyo/tinyexr): EXR image read/write (BSD license) *uses miniz internally* -- **images** [lodepng](http://lodev.org/lodepng/): PNG encoder/decoder (zlib license) -- **images** [nanoSVG](https://github.com/memononen/nanosvg): 1-file SVG parser; 1-file SVG rasterizer (zlib license) -- **3D** [tinyobjloader](https://github.com/syoyo/tinyobjloader): wavefront OBJ file loader (BSD license) -- **2D** [blendish](https://bitbucket.org/duangle/oui-blendish/src): blender-style widget rendering (MIT license) -- **math** [mm_vec.h](https://github.com/vurtun/mmx): vector math (BSD license) -- _**math** [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs): approximate transcendental functions optimized for shaders (esp. GCN) (MIT license)_ -- **geometry** [sdf.h](https://github.com/memononen/SDF): compute signed-distance field from antialiased image (MIT license) -- **geometry** [nanoflann](https://github.com/jlblancoc/nanoflann): build KD trees for point clouds (BSD license) -- **geometry** [jc_voronoi](https://github.com/JCash/voronoi): find voronoi regions on float/double data (MIT license) -- **geometry** [par_msquares](https://github.com/prideout/par): convert (binarized) image to triangles (MIT license) -- **geometry** [tk_objfile](https://github.com/joeld42/tk_objfile): OBJ file loader (MIT license) -- **geometry** [par_shapes](http://github.prideout.net/shapes/): generate various 3d geometric shapes (MIT license) -- **network** [mm_web.h](https://github.com/vurtun/mmx): lightweight webserver, fork of webby (BSD license) -- **network** [par_easycurl.h](https://github.com/prideout/par): curl wrapper (MIT license) -- **audio** [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h): IMA-ADPCM audio decoder (MIT license) -- **multithreading** [mm_sched.h](https://github.com/vurtun/mmx): cross-platform multithreaded task scheduler (zlib license) -- **parsing** [SLRE](https://github.com/cesanta/slre): regular expression matcher (GPL v2) -- **parsing** [PicoJSON](https://github.com/kazuho/picojson): JSON parse/serializer for C++ (BSD license) -- **parsing** [mm_json.h](https://github.com/vurtun/mmx): JSON parser (zlib license) -- **parsing** [mm_lexer.h](https://github.com/vurtun/mmx): C-esque language lexer (zlib license) -- **tests** [utest](https://github.com/evolutional/utest): unit testing (MIT license) -- **tests** [catch](https://github.com/philsquared/Catch): unit testing (Boost license) -- **tests** [SPUT](http://www.lingua-systems.com/unit-testing/): unit testing (BSD license) -- **misc** [lualite](https://github.com/janezz55/lualite/): generate lua bindings in C++ (MIT license) -- **misc** [tinyformat](https://github.com/c42f/tinyformat): C++ typesafe printf (Boost license) +category | library | license | # files | description +-------- | ------- | ------- | ------- | ----------- +2D | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | **1** | blender-style widget rendering +2D | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows +2D | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator +3D | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | **1** | wavefront OBJ file loader +3D | [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/) | zlib | 2 | compute tangent space for normal mapping +AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | 2 | pathfinding with A* +audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | **1** | IMA-ADPCM audio decoder +compression | [miniz.c](https://github.com/richgel999/miniz) | **public domain** | 2 | zlib compression,decompression, zip file, png writing +compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | 2 | fast but larger LZ compression +compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk) | MIT | 2 | fast but larger LZ compression +compression | [pithy](https://github.com/johnezang/pithy) | BSD | 2 | fast but larger LZ compression +crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library +data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | 2 | many 2-file libs: hash, sort, b-tree, etc +data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | 2 | several 1-header, 1-license-file libs: generic hash, list, etc +data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | 2 | memory-efficient array of elements with non-pow2 bitcount +data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) +files&filenames|**[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +files & filenames | [whereami](https://github.com/gpakosz/whereami) | **WTFPLv2** | 2 | get path/filename of executable or module +geometry | **[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)**|**public domain**|**1**|find voronoi regions on lattice w/ integer inputs +geometry | **[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h)**|**public domain**|**1**|sobol & stratified sampling sequences +geometry | [sdf.h](https://github.com/memononen/SDF) | MIT | **1** | compute signed-distance field from antialiased image +geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | **1** | build KD trees for point clouds +geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | **1** | find voronoi regions on float/double data +geometry | [par_msquares](https://github.com/prideout/par) | MIT | **1** | convert (binarized) image to triangles +geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | | **1** | OBJ file loader +geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT | **1** | generate various 3d geometric shapes +geometry | [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/) | **public domain** | 2 | various 3D intersection calculations, not lib-ified +geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | 2 | line & polygon clipping & offsetting +geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | 2 | polygon triangulation, partitioning +hardware| **[EasyTab](https://github.com/ApoorvaJ/EasyTab)**|**public domain**|**1**|multi-platform tablet input +images| **[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)**|**public domain**|**1**|animated GIF writer +images| **[gif.h](https://github.com/ginsweater/gif-h)**|**public domain**|**1**|animated GIF writer +images| **[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h)**|**public domain**|**1**|JPEG encoder +images| **[miniexr](https://github.com/aras-p/miniexr)**|**public domain**|**1**|OpenEXR writer +images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | **1** | EXR image read/write, uses miniz internally +images | [lodepng](http://lodev.org/lodepng/) | zlib | **1** | PNG encoder/decoder +images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | **1** | 1-file SVG parser; 1-file SVG rasterizer +images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | 2 | tiny PNG loader +images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress +math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | **1** | SIMD vector math +math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | **1** | approximate transcendental functions optimized for shaders (esp. GCN) +multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | **1** | cross-platform multithreaded task scheduler +network | **[zed_net](https://github.com/ZedZull/zed_net)**|**public domain**|**1**|cross-platform socket wrapper +network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | **1** | lightweight webserver, fork of webby +network | [par_easycurl.h](https://github.com/prideout/par) | MIT | **1** | curl wrapper +network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server +network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | 2 | http client requests +network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | 2 | http server +network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 +parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | **1** | regular expression matcher +parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | **1** | JSON parse/serializer for C++ +parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | **1** | JSON parser +parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | **1** | C-esque language lexer +parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser +parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | 2 | JSON parser, C++ +parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) +profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer +profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally +scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | **1** | generate lua bindings in C++ +strings | **[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +strings | **[utf8](https://github.com/sheredom/utf8.h)**|**public domain**|**1**|utf8 string library +strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|string interning +strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | 2 | fast utf8 decoder +strings | **[gb_string.h](https://github.com/gingerBill/gb)**|**public domain**|**1**|dynamic strings for C +tests | [utest](https://github.com/evolutional/utest) | MIT | **1** | unit testing +tests | [catch](https://github.com/philsquared/Catch) | Boost | **1** | unit testing +tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | **1** | unit testing +tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src) | **WTFPLv2** | 2 | flexible assertions in C++ +user interface|[dear imgui](https://github.com/ocornut/imgui)|MIT|_many_|an immediate-mode GUI formerly named "ImGui" +misc | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently +misc | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ +misc | [tinyformat](https://github.com/c42f/tinyformat) | Boost | **1** | C++ typesafe printf +misc | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries +misc | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems +misc | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | 2 | compute edit distance between two strings -There are some that have a source file and require a separate header file (which they may -not even supply). That's twice as many files, and we at nothings/stb cannot condone -this! But you might like them anyway: -- **images** [picopng.cpp](http://lodev.org/lodepng/picopng.cpp): tiny PNG loader (zlib license) -- **images** [jpeg-compressor](https://github.com/richgel999/jpeg-compressor): 2-file jpeg compress, 2-file jpeg decompress (public domain) -- **3D** [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/): compute tangent space for normal mapping (zlib) -- **2D** [tigr](https://bitbucket.org/rmitton/tigr/src): quick-n-dirty window text/graphics for Windows (public domain) -- **2D** [noc_turtle](https://github.com/guillaumechereau/noc): procedural graphics generator (public domain) -- **geometry** [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/): various 3D intersection calculations, not lib-ified (public domain) -- **geometry** [Clipper](http://www.angusj.com/delphi/clipper.php): line & polygon clipping & offsetting (Boost license) -- **geometry** [PolyPartition](https://github.com/ivanfratric/polypartition): polygon triangulation, partitioning (MIT license) -- **network** [yocto](https://github.com/tom-seddon/yhs): non-production-use http server (public domain) -- **network** [happyhttp](http://scumways.com/happyhttp/happyhttp.html): http client requests (zlib license) -- **network** [mongoose](https://github.com/cesanta/mongoose): http server (GPL v2) -- _**network** [LUrlParser](https://github.com/corporateshark/LUrlParser): lightweight URL & URI parser RFC 1738, RFC 3986 (MIT license)_ -- **crypto** [TweetNaCl](http://tweetnacl.cr.yp.to/software.html): high-quality tiny cryptography library (public domain) -- **AI** [micropather](http://www.grinninglizard.com/MicroPather/): pathfinding with A* (zlib license) -- **compression** [miniz.c](https://github.com/richgel999/miniz): zlib compression,decompression, zip file, png writing (public domain) -- **compression** [lz4](https://github.com/Cyan4973/lz4): fast but larger LZ compression (BSD license) -- **compression** [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk): fast but larger LZ compression (MIT license) -- **compression** [pithy](https://github.com/johnezang/pithy): fast but larger LZ compression (BSD license) -- **profiling** [Remotery](https://github.com/Celtoys/Remotery): CPU/GPU profiler Win/Mac/Linux, using web browser for viewer (Apache 2.0 license) -- **profiling** [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile): CPU (and GPU?) profiler, 1-3 header files (unlicense) *uses miniz internally* -- **parsing** [json.h](https://github.com/sheredom/json.h): JSON parser (public domain) -- **parsing** [jzon.h](https://github.com/Zguy/Jzon): JSON parser, C++ (MIT license) -- **strings** [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/): fast utf8 decoder (MIT license) -- **data structures** [klib](http://attractivechaos.github.io/klib/): many 2-file libs: hash, sort, b-tree, etc (MIT license) -- **data structures** [uthash](https://github.com/troydhanson/uthash): several 1-header, 1-license-file libs: generic hash, list, etc (BSD license) -- **data structures** [PackedArray](https://github.com/gpakosz/PackedArray): memory-efficient array of elements with non-pow2 bitcount (WTFPL v2 license) -- **data structures**; **algorithms** [minilibs](https://github.com/ccxvii/minilibs): two-file regex, binary tree (public domain) -- **files & filenames** [whereami](https://github.com/gpakosz/whereami): get path/filename of executable or module (WTFPL v2 license) -- **misc** [dbgtools](https://github.com/wc-duck/dbgtools): cross-platform debug util libraries (zlib license) -- **misc** [stmr](https://github.com/wooorm/stmr.c): extract English word stems (MIT license) -- **misc** [levenshtein](https://github.com/wooorm/levenshtein.c): compute edit distance between two strings (MIT license) -- **tests** [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src): flexible assertions in C++ (WTFPL v2 license) +There are also these XML libraries, but if you're using XML, shame on you: -There is also these XML libraries, but if you're using XML, shame on you: - -- **parsing** [tinyxml2](https://github.com/leethomason/tinyxml2): XML (zlib license) -- **parsing** [pugixml](http://pugixml.org/): XML (MIT license) +- parsing: [tinyxml2](https://github.com/leethomason/tinyxml2): XML +- parsing: [pugixml](http://pugixml.org/): XML (MIT license) There are some libraries that are just _so_ awesome that even though they use more than two files we're going to give them special dispensation to appear in their own little list here. If you're a crazy purist, be warned, but otherwise, enjoy! -- **user interface** [dear imgui](https://github.com/ocornut/imgui): an immediate-mode GUI ("imgui") named "ImGui" (MIT license) - Also you might be interested in other related, but different lists: - [clib](https://github.com/clibs/clib/wiki/Packages): list of (mostly) small single C functions (licenses not listed) From 19223d2f0a2164e731f77cce327450708825f673 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 07:01:14 -0800 Subject: [PATCH 221/522] avoid line-break in "public domain" --- docs/other_libs.md | 50 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0e98907..8b5f074 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -12,51 +12,51 @@ free to tell me about their quality. category | library | license | # files | description -------- | ------- | ------- | ------- | ----------- 2D | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | **1** | blender-style widget rendering -2D | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows -2D | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator +2D | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows +2D | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator 3D | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | **1** | wavefront OBJ file loader 3D | [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/) | zlib | 2 | compute tangent space for normal mapping AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | 2 | pathfinding with A* audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | **1** | IMA-ADPCM audio decoder -compression | [miniz.c](https://github.com/richgel999/miniz) | **public domain** | 2 | zlib compression,decompression, zip file, png writing +compression | [miniz.c](https://github.com/richgel999/miniz) | **public domain** | 2 | zlib compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk) | MIT | 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD | 2 | fast but larger LZ compression -crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library +crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | 2 | memory-efficient array of elements with non-pow2 bitcount -data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) -files&filenames|**[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) +files&filenames|**[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) | **WTFPLv2** | 2 | get path/filename of executable or module -geometry | **[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)**|**public domain**|**1**|find voronoi regions on lattice w/ integer inputs -geometry | **[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h)**|**public domain**|**1**|sobol & stratified sampling sequences +geometry | **[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)**|**public domain**|**1**|find voronoi regions on lattice w/ integer inputs +geometry | **[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h)**|**public domain**|**1**|sobol & stratified sampling sequences geometry | [sdf.h](https://github.com/memononen/SDF) | MIT | **1** | compute signed-distance field from antialiased image geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | **1** | build KD trees for point clouds geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | **1** | find voronoi regions on float/double data geometry | [par_msquares](https://github.com/prideout/par) | MIT | **1** | convert (binarized) image to triangles geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | | **1** | OBJ file loader geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT | **1** | generate various 3d geometric shapes -geometry | [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/) | **public domain** | 2 | various 3D intersection calculations, not lib-ified +geometry | [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/) | **public domain** | 2 | various 3D intersection calculations, not lib-ified geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | 2 | line & polygon clipping & offsetting geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | 2 | polygon triangulation, partitioning -hardware| **[EasyTab](https://github.com/ApoorvaJ/EasyTab)**|**public domain**|**1**|multi-platform tablet input -images| **[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)**|**public domain**|**1**|animated GIF writer -images| **[gif.h](https://github.com/ginsweater/gif-h)**|**public domain**|**1**|animated GIF writer -images| **[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h)**|**public domain**|**1**|JPEG encoder -images| **[miniexr](https://github.com/aras-p/miniexr)**|**public domain**|**1**|OpenEXR writer +hardware| **[EasyTab](https://github.com/ApoorvaJ/EasyTab)**|**public domain**|**1**|multi-platform tablet input +images| **[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)**|**public domain**|**1**|animated GIF writer +images| **[gif.h](https://github.com/ginsweater/gif-h)**|**public domain**|**1**|animated GIF writer +images| **[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h)**|**public domain**|**1**|JPEG encoder +images| **[miniexr](https://github.com/aras-p/miniexr)**|**public domain**|**1**|OpenEXR writer images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | **1** | EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib | **1** | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | **1** | 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | 2 | tiny PNG loader -images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress +images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | **1** | SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | **1** | approximate transcendental functions optimized for shaders (esp. GCN) multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | **1** | cross-platform multithreaded task scheduler -network | **[zed_net](https://github.com/ZedZull/zed_net)**|**public domain**|**1**|cross-platform socket wrapper +network | **[zed_net](https://github.com/ZedZull/zed_net)**|**public domain**|**1**|cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | **1** | lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT | **1** | curl wrapper -network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server +network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | 2 | http client requests network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | 2 | http server network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 @@ -64,24 +64,24 @@ parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | **1** | regular expr parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | **1** | JSON parse/serializer for C++ parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | **1** | JSON parser parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | **1** | C-esque language lexer -parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser +parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | 2 | JSON parser, C++ -parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) +parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | **1** | generate lua bindings in C++ -strings | **[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -strings | **[utf8](https://github.com/sheredom/utf8.h)**|**public domain**|**1**|utf8 string library -strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|string interning +strings | **[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +strings | **[utf8](https://github.com/sheredom/utf8.h)**|**public domain**|**1**|utf8 string library +strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | 2 | fast utf8 decoder -strings | **[gb_string.h](https://github.com/gingerBill/gb)**|**public domain**|**1**|dynamic strings for C +strings | **[gb_string.h](https://github.com/gingerBill/gb)**|**public domain**|**1**|dynamic strings for C tests | [utest](https://github.com/evolutional/utest) | MIT | **1** | unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | **1** | unit testing tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | **1** | unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src) | **WTFPLv2** | 2 | flexible assertions in C++ user interface|[dear imgui](https://github.com/ocornut/imgui)|MIT|_many_|an immediate-mode GUI formerly named "ImGui" -misc | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently -misc | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ +misc | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently +misc | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ misc | [tinyformat](https://github.com/c42f/tinyformat) | Boost | **1** | C++ typesafe printf misc | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries misc | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems From d712fafeb1ea72c73e0747dc1db40d7ef3696645 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 07:01:56 -0800 Subject: [PATCH 222/522] fix last check-in --- docs/other_libs.md | 50 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8b5f074..d0c7644 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -12,51 +12,51 @@ free to tell me about their quality. category | library | license | # files | description -------- | ------- | ------- | ------- | ----------- 2D | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | **1** | blender-style widget rendering -2D | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows -2D | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator +2D | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows +2D | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator 3D | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | **1** | wavefront OBJ file loader 3D | [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/) | zlib | 2 | compute tangent space for normal mapping AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | 2 | pathfinding with A* audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | **1** | IMA-ADPCM audio decoder -compression | [miniz.c](https://github.com/richgel999/miniz) | **public domain** | 2 | zlib compression,decompression, zip file, png writing +compression | [miniz.c](https://github.com/richgel999/miniz) | **public domain** | 2 | zlib compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk) | MIT | 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD | 2 | fast but larger LZ compression -crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library +crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | 2 | memory-efficient array of elements with non-pow2 bitcount -data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) -files&filenames|**[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) +files&filenames|**[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) | **WTFPLv2** | 2 | get path/filename of executable or module -geometry | **[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)**|**public domain**|**1**|find voronoi regions on lattice w/ integer inputs -geometry | **[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h)**|**public domain**|**1**|sobol & stratified sampling sequences +geometry | **[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)**|**public domain**|**1**|find voronoi regions on lattice w/ integer inputs +geometry | **[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h)**|**public domain**|**1**|sobol & stratified sampling sequences geometry | [sdf.h](https://github.com/memononen/SDF) | MIT | **1** | compute signed-distance field from antialiased image geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | **1** | build KD trees for point clouds geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | **1** | find voronoi regions on float/double data geometry | [par_msquares](https://github.com/prideout/par) | MIT | **1** | convert (binarized) image to triangles geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | | **1** | OBJ file loader geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT | **1** | generate various 3d geometric shapes -geometry | [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/) | **public domain** | 2 | various 3D intersection calculations, not lib-ified +geometry | [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/) | **public domain** | 2 | various 3D intersection calculations, not lib-ified geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | 2 | line & polygon clipping & offsetting geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | 2 | polygon triangulation, partitioning -hardware| **[EasyTab](https://github.com/ApoorvaJ/EasyTab)**|**public domain**|**1**|multi-platform tablet input -images| **[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)**|**public domain**|**1**|animated GIF writer -images| **[gif.h](https://github.com/ginsweater/gif-h)**|**public domain**|**1**|animated GIF writer -images| **[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h)**|**public domain**|**1**|JPEG encoder -images| **[miniexr](https://github.com/aras-p/miniexr)**|**public domain**|**1**|OpenEXR writer +hardware| **[EasyTab](https://github.com/ApoorvaJ/EasyTab)**|**public domain**|**1**|multi-platform tablet input +images| **[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)**|**public domain**|**1**|animated GIF writer +images| **[gif.h](https://github.com/ginsweater/gif-h)**|**public domain**|**1**|animated GIF writer +images| **[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h)**|**public domain**|**1**|JPEG encoder +images| **[miniexr](https://github.com/aras-p/miniexr)**|**public domain**|**1**|OpenEXR writer images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | **1** | EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib | **1** | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | **1** | 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | 2 | tiny PNG loader -images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress +images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | **1** | SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | **1** | approximate transcendental functions optimized for shaders (esp. GCN) multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | **1** | cross-platform multithreaded task scheduler -network | **[zed_net](https://github.com/ZedZull/zed_net)**|**public domain**|**1**|cross-platform socket wrapper +network | **[zed_net](https://github.com/ZedZull/zed_net)**|**public domain**|**1**|cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | **1** | lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT | **1** | curl wrapper -network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server +network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | 2 | http client requests network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | 2 | http server network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 @@ -64,24 +64,24 @@ parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | **1** | regular expr parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | **1** | JSON parse/serializer for C++ parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | **1** | JSON parser parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | **1** | C-esque language lexer -parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser +parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | 2 | JSON parser, C++ -parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) +parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | **1** | generate lua bindings in C++ -strings | **[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -strings | **[utf8](https://github.com/sheredom/utf8.h)**|**public domain**|**1**|utf8 string library -strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|string interning +strings | **[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +strings | **[utf8](https://github.com/sheredom/utf8.h)**|**public domain**|**1**|utf8 string library +strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | 2 | fast utf8 decoder -strings | **[gb_string.h](https://github.com/gingerBill/gb)**|**public domain**|**1**|dynamic strings for C +strings | **[gb_string.h](https://github.com/gingerBill/gb)**|**public domain**|**1**|dynamic strings for C tests | [utest](https://github.com/evolutional/utest) | MIT | **1** | unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | **1** | unit testing tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | **1** | unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src) | **WTFPLv2** | 2 | flexible assertions in C++ user interface|[dear imgui](https://github.com/ocornut/imgui)|MIT|_many_|an immediate-mode GUI formerly named "ImGui" -misc | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently -misc | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ +misc | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently +misc | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ misc | [tinyformat](https://github.com/c42f/tinyformat) | Boost | **1** | C++ typesafe printf misc | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries misc | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems From eb84b2179b059aef3a0ceb5fc9a8b66b9de81234 Mon Sep 17 00:00:00 2001 From: Socks the Fox Date: Mon, 18 Jan 2016 10:42:41 -0600 Subject: [PATCH 223/522] Initial 16 bit per channel PNG support --- stb_image.h | 133 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 113 insertions(+), 20 deletions(-) diff --git a/stb_image.h b/stb_image.h index be25097..daa47ae 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3938,6 +3938,7 @@ typedef struct { stbi__context *s; stbi_uc *idata, *expanded, *out; + int depth; } stbi__png; @@ -3977,14 +3978,19 @@ static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x0 // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { + int bytes = (depth == 16? 2 : 1); stbi__context *s = a->s; - stbi__uint32 i,j,stride = x*out_n; + stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 img_len, img_width_bytes; int k; int img_n = s->img_n; // copy it into a local for later + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into + a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); @@ -3999,8 +4005,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r stbi_uc *cur = a->out + stride*j; stbi_uc *prior = cur - stride; int filter = *raw++; - int filter_bytes = img_n; - int width = x; + if (filter > 4) return stbi__err("invalid filter","Corrupt PNG"); @@ -4033,6 +4038,14 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r raw += img_n; cur += out_n; prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; } else { raw += 1; cur += 1; @@ -4041,7 +4054,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r // this is a little gross, so that we don't switch per-pixel or per-component if (depth < 8 || img_n == out_n) { - int nk = (width - 1)*img_n; + int nk = (width - 1)*filter_bytes; #define CASE(f) \ case f: \ for (k=0; k < nk; ++k) @@ -4061,18 +4074,27 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r STBI_ASSERT(img_n+1 == out_n); #define CASE(f) \ case f: \ - for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ - for (k=0; k < img_n; ++k) + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) switch (filter) { CASE(STBI__F_none) cur[k] = raw[k]; break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break; CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break; } #undef CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } } } @@ -4148,6 +4170,17 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r } } } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } } return 1; @@ -4220,6 +4253,31 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) return 1; } +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) { stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; @@ -4257,6 +4315,26 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int return 1; } +static int stbi__reduce_png(stbi__png *p) +{ + int i; + int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n; + stbi_uc *reduced; + stbi__uint16 *orig = (stbi__uint16*)p->out; + + if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data + + reduced = (stbi_uc *)stbi__malloc(img_len); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling + + p->out = reduced; + STBI_FREE(orig); + + return 1; +} + static int stbi__unpremultiply_on_load = 0; static int stbi__de_iphone_flag = 0; @@ -4318,8 +4396,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { stbi_uc palette[1024], pal_img_n=0; stbi_uc has_trans=0, tc[3]; + stbi__uint16 tc16[3]; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; - int first=1,k,interlace=0, color=0, depth=0, is_iphone=0; + int first=1,k,interlace=0, color=0, is_iphone=0; stbi__context *s = z->s; z->expanded = NULL; @@ -4344,8 +4423,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); - depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); @@ -4393,8 +4473,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; - for (k=0; k < s->img_n; ++k) - tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } } break; } @@ -4424,7 +4507,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (scan != STBI__SCAN_load) return 1; if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); // initial guess for decoded data size to avoid unnecessary reallocs - bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); if (z->expanded == NULL) return 0; // zlib should set error @@ -4433,9 +4516,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) s->img_out_n = s->img_n+1; else s->img_out_n = s->img_n; - if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0; - if (has_trans) - if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) stbi__de_iphone(z); if (pal_img_n) { @@ -4477,6 +4565,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req unsigned char *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth == 16) { + if (!stbi__reduce_png(p)) { + return result; + } + } result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { From b373cf536a48723e19ea30e0ae336680345c1325 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 12:37:11 -0800 Subject: [PATCH 224/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index d0c7644..9e335b3 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -9,7 +9,7 @@ free to tell me about their quality. **Public domain single-file libraries are in bold.** -category | library | license | # files | description +category | library | license | files | description -------- | ------- | ------- | ------- | ----------- 2D | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | **1** | blender-style widget rendering 2D | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows @@ -72,7 +72,7 @@ profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **un scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | **1** | generate lua bindings in C++ strings | **[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings | **[utf8](https://github.com/sheredom/utf8.h)**|**public domain**|**1**|utf8 string library -strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|string interning +strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|**1**|string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | 2 | fast utf8 decoder strings | **[gb_string.h](https://github.com/gingerBill/gb)**|**public domain**|**1**|dynamic strings for C tests | [utest](https://github.com/evolutional/utest) | MIT | **1** | unit testing From 43e845d7109bc26ae81bed1a5737198c6544025b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 12:38:35 -0800 Subject: [PATCH 225/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 9e335b3..43f3502 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -79,7 +79,7 @@ tests | [utest](https://github.com/evolutional/utest) | MIT | **1** | unit testi tests | [catch](https://github.com/philsquared/Catch) | Boost | **1** | unit testing tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | **1** | unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src) | **WTFPLv2** | 2 | flexible assertions in C++ -user interface|[dear imgui](https://github.com/ocornut/imgui)|MIT|_many_|an immediate-mode GUI formerly named "ImGui" +user interface|[dear imgui](https://github.com/ocornut/imgui)|MIT|9|an immediate-mode GUI formerly named "ImGui" misc | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently misc | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ misc | [tinyformat](https://github.com/c42f/tinyformat) | Boost | **1** | C++ typesafe printf From ff51a1bd6b9699fb20fa5c495e835e6742b23a08 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 12:40:13 -0800 Subject: [PATCH 226/522] Update other_libs.md --- docs/other_libs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 43f3502..28e967d 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -6,7 +6,8 @@ People have told me about quite a few of these. However, I haven't used most of and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality. -**Public domain single-file libraries are in bold.** +**Public domain single-file libraries are in bold.** Other libraries are either non-public domain, +or two files, or both. category | library | license | files | description From 32c2bfad333f75e8b8dc002581bd0c33d8b41b26 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 22 Jan 2016 12:41:46 -0800 Subject: [PATCH 227/522] Update other_libs.md --- docs/other_libs.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 28e967d..32e36aa 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -12,11 +12,6 @@ or two files, or both. category | library | license | files | description -------- | ------- | ------- | ------- | ----------- -2D | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | **1** | blender-style widget rendering -2D | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows -2D | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator -3D | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | **1** | wavefront OBJ file loader -3D | [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/) | zlib | 2 | compute tangent space for normal mapping AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | 2 | pathfinding with A* audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | **1** | IMA-ADPCM audio decoder compression | [miniz.c](https://github.com/richgel999/miniz) | **public domain** | 2 | zlib compression,decompression, zip file, png writing @@ -41,6 +36,11 @@ geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT | **1** | gene geometry | [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/) | **public domain** | 2 | various 3D intersection calculations, not lib-ified geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | 2 | line & polygon clipping & offsetting geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | 2 | polygon triangulation, partitioning +graphics (2D) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | **1** | blender-style widget rendering +graphics (2D) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows +graphics (2D) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator +graphics (3D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | **1** | wavefront OBJ file loader +graphics (3D) | [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/) | zlib | 2 | compute tangent space for normal mapping hardware| **[EasyTab](https://github.com/ApoorvaJ/EasyTab)**|**public domain**|**1**|multi-platform tablet input images| **[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)**|**public domain**|**1**|animated GIF writer images| **[gif.h](https://github.com/ginsweater/gif-h)**|**public domain**|**1**|animated GIF writer @@ -81,12 +81,12 @@ tests | [catch](https://github.com/philsquared/Catch) | Boost | **1** | unit tes tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | **1** | unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src) | **WTFPLv2** | 2 | flexible assertions in C++ user interface|[dear imgui](https://github.com/ocornut/imgui)|MIT|9|an immediate-mode GUI formerly named "ImGui" -misc | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently -misc | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ -misc | [tinyformat](https://github.com/c42f/tinyformat) | Boost | **1** | C++ typesafe printf -misc | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries -misc | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems -misc | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | 2 | compute edit distance between two strings +_misc_ | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently +_misc_ | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ +_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | **1** | C++ typesafe printf +_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries +_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems +_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | 2 | compute edit distance between two strings There are also these XML libraries, but if you're using XML, shame on you: From d4f552b39377d9bce44e492ef972f5ab1203ef97 Mon Sep 17 00:00:00 2001 From: Lukas Meller Date: Sat, 23 Jan 2016 03:41:03 +0100 Subject: [PATCH 228/522] Fixed typo --- stb_leakcheck.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_leakcheck.h b/stb_leakcheck.h index 7e49fc9..bac4c72 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -6,7 +6,7 @@ // distribute, and modify this file as you see fit. #ifdef STB_LEAKCHECK_IMPLEMENTATION -#undef STB_LEAKCHECK_IMPLEMENTATION // don't implenment more than once +#undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once // if we've already included leakcheck before, undefine the macros #ifdef malloc From 5bcfa002429b7397396ae620ced51199d0b7ff9b Mon Sep 17 00:00:00 2001 From: Krzysztof Gabis Date: Sat, 23 Jan 2016 10:05:57 +0000 Subject: [PATCH 229/522] Adds parson to other_libs.md Parson is a 2-file (.h and .c) JSON parser and serializer written in C. --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 32e36aa..327142e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -67,6 +67,7 @@ parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | **1** | JSON parse parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | **1** | C-esque language lexer parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | 2 | JSON parser, C++ +parsing | [parson](https://github.com/kgabis/parson) | MIT | 2 | JSON parser and serializer, C parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally From 99dc799f2a241af62da754418a6b240a6c267561 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 05:09:04 -0800 Subject: [PATCH 230/522] reformat other_libs source to prepare for new columns --- docs/other_libs.md | 157 ++++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 79 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 327142e..0fd46b9 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -10,85 +10,84 @@ free to tell me about their quality. or two files, or both. -category | library | license | files | description --------- | ------- | ------- | ------- | ----------- -AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | 2 | pathfinding with A* -audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | **1** | IMA-ADPCM audio decoder -compression | [miniz.c](https://github.com/richgel999/miniz) | **public domain** | 2 | zlib compression,decompression, zip file, png writing -compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | 2 | fast but larger LZ compression -compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk) | MIT | 2 | fast but larger LZ compression -compression | [pithy](https://github.com/johnezang/pithy) | BSD | 2 | fast but larger LZ compression -crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library -data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | 2 | many 2-file libs: hash, sort, b-tree, etc -data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | 2 | several 1-header, 1-license-file libs: generic hash, list, etc -data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | 2 | memory-efficient array of elements with non-pow2 bitcount -data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) -files&filenames|**[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -files & filenames | [whereami](https://github.com/gpakosz/whereami) | **WTFPLv2** | 2 | get path/filename of executable or module -geometry | **[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)**|**public domain**|**1**|find voronoi regions on lattice w/ integer inputs -geometry | **[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/blob/master/src/SFH/Sobol.h)**|**public domain**|**1**|sobol & stratified sampling sequences -geometry | [sdf.h](https://github.com/memononen/SDF) | MIT | **1** | compute signed-distance field from antialiased image -geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | **1** | build KD trees for point clouds -geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | **1** | find voronoi regions on float/double data -geometry | [par_msquares](https://github.com/prideout/par) | MIT | **1** | convert (binarized) image to triangles -geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | | **1** | OBJ file loader -geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT | **1** | generate various 3d geometric shapes -geometry | [Tomas Akenine-Moller snippets](http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/) | **public domain** | 2 | various 3D intersection calculations, not lib-ified -geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | 2 | line & polygon clipping & offsetting -geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | 2 | polygon triangulation, partitioning -graphics (2D) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | **1** | blender-style widget rendering -graphics (2D) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows -graphics (2D) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator -graphics (3D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | **1** | wavefront OBJ file loader -graphics (3D) | [mikktspace](https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/) | zlib | 2 | compute tangent space for normal mapping -hardware| **[EasyTab](https://github.com/ApoorvaJ/EasyTab)**|**public domain**|**1**|multi-platform tablet input -images| **[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)**|**public domain**|**1**|animated GIF writer -images| **[gif.h](https://github.com/ginsweater/gif-h)**|**public domain**|**1**|animated GIF writer -images| **[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h)**|**public domain**|**1**|JPEG encoder -images| **[miniexr](https://github.com/aras-p/miniexr)**|**public domain**|**1**|OpenEXR writer -images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | **1** | EXR image read/write, uses miniz internally -images | [lodepng](http://lodev.org/lodepng/) | zlib | **1** | PNG encoder/decoder -images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | **1** | 1-file SVG parser; 1-file SVG rasterizer -images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | 2 | tiny PNG loader -images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress -math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | **1** | SIMD vector math -math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | **1** | approximate transcendental functions optimized for shaders (esp. GCN) -multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | **1** | cross-platform multithreaded task scheduler -network | **[zed_net](https://github.com/ZedZull/zed_net)**|**public domain**|**1**|cross-platform socket wrapper -network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | **1** | lightweight webserver, fork of webby -network | [par_easycurl.h](https://github.com/prideout/par) | MIT | **1** | curl wrapper -network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server -network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | 2 | http client requests -network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | 2 | http server -network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 -parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | **1** | regular expression matcher -parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | **1** | JSON parse/serializer for C++ -parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | **1** | JSON parser -parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | **1** | C-esque language lexer -parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser -parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | 2 | JSON parser, C++ -parsing | [parson](https://github.com/kgabis/parson) | MIT | 2 | JSON parser and serializer, C -parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) -profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer -profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally -scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | **1** | generate lua bindings in C++ -strings | **[DG_misc.h](https://github.com/DanielGibson/Snippets/)**|**public domain**|**1**|Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -strings | **[utf8](https://github.com/sheredom/utf8.h)**|**public domain**|**1**|utf8 string library -strings | **[strpool.h](https://github.com/mattiasgustavsson/libs)**|**public domain**/MIT|**1**|string interning -strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | 2 | fast utf8 decoder -strings | **[gb_string.h](https://github.com/gingerBill/gb)**|**public domain**|**1**|dynamic strings for C -tests | [utest](https://github.com/evolutional/utest) | MIT | **1** | unit testing -tests | [catch](https://github.com/philsquared/Catch) | Boost | **1** | unit testing -tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | **1** | unit testing -tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert/tree/master/src) | **WTFPLv2** | 2 | flexible assertions in C++ -user interface|[dear imgui](https://github.com/ocornut/imgui)|MIT|9|an immediate-mode GUI formerly named "ImGui" -_misc_ | **[MakeID.h](http://www.humus.name/3D/MakeID.h)**|**public domain**|**1**|allocate/deallocate small integer IDs efficiently -_misc_ | **[loguru](https://github.com/emilk/loguru)**|**public domain**|**1**|flexible logging for C++ -_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | **1** | C++ typesafe printf -_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries -_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems -_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | 2 | compute edit distance between two strings - +category | library | license |files| description +----------------- | --------------------------------------------------------------------- | -------------------- | --- | ----------- +AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | 2 | pathfinding with A* +audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |**1**| IMA-ADPCM audio decoder +compression | [miniz.c](https://github.com/richgel999/miniz) |**public domain**| 2 | zlib | compression,decompression, zip file, png writing +compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | 2 | fast but larger LZ compression +compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT | 2 | fast but larger LZ compression +compression | [pithy](https://github.com/johnezang/pithy) | BSD | 2 | fast but larger LZ compression +crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library +data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | 2 | many 2-file libs: hash, sort, b-tree, etc +data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | 2 | several 1-header, 1-license-file libs: generic hash, list, etc +data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | 2 | memory-efficient array of elements with non-pow2 bitcount +data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) +files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** | 2 | get path/filename of executable or module +geometry |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |**1**| find voronoi regions on lattice w/ integer inputs +geometry |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |**1**| sobol & stratified sampling sequences +geometry | [sdf.h](https://github.com/memononen/SDF) | MIT |**1**| compute signed-distance field from antialiased image +geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD |**1**| build KD trees for point clouds +geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT |**1**| find voronoi regions on float/double data +geometry | [par_msquares](https://github.com/prideout/par) | MIT |**1**| convert (binarized) image to triangles +geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |**1**| OBJ file loader +geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT |**1**| generate various 3d geometric shapes +geometry | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | 2 | various 3D intersection calculations, not lib-ified +geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | 2 | line & polygon clipping & offsetting +geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | 2 | polygon triangulation, partitioning +graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |**1**| blender-style widget rendering +graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows +graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator +graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD |**1**| wavefront OBJ file loader +graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | 2 | compute tangent space for normal mapping +hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |**1**| multi-platform tablet input +images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** |**1**| animated GIF writer +images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** |**1**| animated GIF writer +images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |**1**| JPEG encoder +images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** |**1**| OpenEXR writer +images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |**1**| EXR image read/write, uses miniz internally +images | [lodepng](http://lodev.org/lodepng/) | zlib |**1**| PNG encoder/decoder +images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |**1**| 1-file SVG parser; 1-file SVG rasterizer +images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | 2 | tiny PNG loader +images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress +math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |**1**| SIMD vector math +math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT |**1**| approximate transcendental functions optimized for shaders (esp. GCN) +multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |**1**| cross-platform multithreaded task scheduler +network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |**1**| cross-platform socket wrapper +network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |**1**| lightweight webserver, fork of webby +network | [par_easycurl.h](https://github.com/prideout/par) | MIT |**1**| curl wrapper +network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server +network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | 2 | http client requests +network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | 2 | http server +network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 +parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 |**1**| regular expression matcher +parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD |**1**| JSON parse/serializer for C++ +parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib |**1**| JSON parser +parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib |**1**| C-esque language lexer +parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser +parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | 2 | JSON parser, C++ +parsing | [parson](https://github.com/kgabis/parson) | MIT | 2 | JSON parser and serializer, C +parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) +profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer +profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally +scripting | [lualite](https://github.com/janezz55/lualite/) | MIT |**1**| generate lua bindings in C++ +strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |**1**| utf8 string library +strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** |**1**| string interning +strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | 2 | fast utf8 decoder +strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |**1**| dynamic strings for C +tests | [utest](https://github.com/evolutional/utest) | MIT |**1**| unit testing +tests | [catch](https://github.com/philsquared/Catch) | Boost |**1**| unit testing +tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD |**1**| unit testing +tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | 2 | flexible assertions in C++ +user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | 9 | an immediate-mode GUI formerly named "ImGui" +_misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** | **public domain** |**1**| allocate/deallocate small integer IDs efficiently +_misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** |**1**| flexible logging for C++ +_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost |**1**| C++ typesafe printf +_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries +_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems +_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | 2 | compute edit distance between two strings There are also these XML libraries, but if you're using XML, shame on you: From 9bbc3ae812417ffec9c1b860458b2e455223b96b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 05:25:35 -0800 Subject: [PATCH 231/522] other_libs: indicate whether libraries are usable from C or C++ --- docs/other_libs.md | 174 ++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 89 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0fd46b9..cea95ff 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -6,98 +6,94 @@ People have told me about quite a few of these. However, I haven't used most of and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality. -**Public domain single-file libraries are in bold.** Other libraries are either non-public domain, -or two files, or both. +**Public domain single-file libraries usable from C are in bold.** Other libraries are either non-public domain, +or two files, or only usable from C++, or all three. (As of this writing, the usability-from-C is unknown for +many libraries, and the benefit of the doubt is given for boldfacing.) - -category | library | license |files| description ------------------ | --------------------------------------------------------------------- | -------------------- | --- | ----------- -AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | 2 | pathfinding with A* -audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |**1**| IMA-ADPCM audio decoder -compression | [miniz.c](https://github.com/richgel999/miniz) |**public domain**| 2 | zlib | compression,decompression, zip file, png writing -compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | 2 | fast but larger LZ compression -compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT | 2 | fast but larger LZ compression -compression | [pithy](https://github.com/johnezang/pithy) | BSD | 2 | fast but larger LZ compression -crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | 2 | high-quality tiny cryptography library -data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | 2 | many 2-file libs: hash, sort, b-tree, etc -data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | 2 | several 1-header, 1-license-file libs: generic hash, list, etc -data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | 2 | memory-efficient array of elements with non-pow2 bitcount -data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file binary tress (also regex, etc) -files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** | 2 | get path/filename of executable or module -geometry |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |**1**| find voronoi regions on lattice w/ integer inputs -geometry |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |**1**| sobol & stratified sampling sequences -geometry | [sdf.h](https://github.com/memononen/SDF) | MIT |**1**| compute signed-distance field from antialiased image -geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD |**1**| build KD trees for point clouds -geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT |**1**| find voronoi regions on float/double data -geometry | [par_msquares](https://github.com/prideout/par) | MIT |**1**| convert (binarized) image to triangles -geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |**1**| OBJ file loader -geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT |**1**| generate various 3d geometric shapes -geometry | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | 2 | various 3D intersection calculations, not lib-ified -geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | 2 | line & polygon clipping & offsetting -geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | 2 | polygon triangulation, partitioning -graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |**1**| blender-style widget rendering -graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | 2 | quick-n-dirty window text/graphics for Windows -graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | 2 | procedural graphics generator -graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD |**1**| wavefront OBJ file loader -graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | 2 | compute tangent space for normal mapping -hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |**1**| multi-platform tablet input -images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** |**1**| animated GIF writer -images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** |**1**| animated GIF writer -images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |**1**| JPEG encoder -images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** |**1**| OpenEXR writer -images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |**1**| EXR image read/write, uses miniz internally -images | [lodepng](http://lodev.org/lodepng/) | zlib |**1**| PNG encoder/decoder -images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |**1**| 1-file SVG parser; 1-file SVG rasterizer -images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | 2 | tiny PNG loader -images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | 2 | 2-file jpeg compress, 2-file jpeg decompress -math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |**1**| SIMD vector math -math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT |**1**| approximate transcendental functions optimized for shaders (esp. GCN) -multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |**1**| cross-platform multithreaded task scheduler -network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |**1**| cross-platform socket wrapper -network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |**1**| lightweight webserver, fork of webby -network | [par_easycurl.h](https://github.com/prideout/par) | MIT |**1**| curl wrapper -network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | 2 | non-production-use http server -network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | 2 | http client requests -network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | 2 | http server -network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 -parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 |**1**| regular expression matcher -parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD |**1**| JSON parse/serializer for C++ -parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib |**1**| JSON parser -parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib |**1**| C-esque language lexer -parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | 2 | JSON parser -parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | 2 | JSON parser, C++ -parsing | [parson](https://github.com/kgabis/parson) | MIT | 2 | JSON parser and serializer, C -parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | 2 | two-file regex (also binary tree, etc) -profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer -profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally -scripting | [lualite](https://github.com/janezz55/lualite/) | MIT |**1**| generate lua bindings in C++ -strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |**1**| utf8 string library -strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** |**1**| string interning -strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | 2 | fast utf8 decoder -strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |**1**| dynamic strings for C -tests | [utest](https://github.com/evolutional/utest) | MIT |**1**| unit testing -tests | [catch](https://github.com/philsquared/Catch) | Boost |**1**| unit testing -tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD |**1**| unit testing -tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | 2 | flexible assertions in C++ -user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | 9 | an immediate-mode GUI formerly named "ImGui" -_misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** | **public domain** |**1**| allocate/deallocate small integer IDs efficiently -_misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** |**1**| flexible logging for C++ -_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost |**1**| C++ typesafe printf -_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | 2 | cross-platform debug util libraries -_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | 2 | extract English word stems -_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | 2 | compute edit distance between two strings - -There are also these XML libraries, but if you're using XML, shame on you: - -- parsing: [tinyxml2](https://github.com/leethomason/tinyxml2): XML +category | library | license | API |files| description +----------------- | --------------------------------------------------------------------- | -------------------- | --- | --- | ----------- +AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | | 2 | pathfinding with A* +audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | |**1**| IMA-ADPCM audio decoder +compression | [miniz.c](https://github.com/richgel999/miniz) |**public domain**| C | 2 | compression,decompression, zip file, png writing +compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | | 2 | fast but larger LZ compression +compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT | | 2 | fast but larger LZ compression +compression | [pithy](https://github.com/johnezang/pithy) | BSD | | 2 | fast but larger LZ compression +crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | | 2 | high-quality tiny cryptography library +data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc +data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc +data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | | 2 | memory-efficient array of elements with non-pow2 bitcount +data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) +files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** | | 2 | get path/filename of executable or module +geometry |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs +geometry |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** | |**1**| sobol & stratified sampling sequences +geometry | [sdf.h](https://github.com/memononen/SDF) | MIT | |**1**| compute signed-distance field from antialiased image +geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | |**1**| build KD trees for point clouds +geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | |**1**| find voronoi regions on float/double data +geometry | [par_msquares](https://github.com/prideout/par) | MIT | |**1**| convert (binarized) image to triangles +geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT | |**1**| OBJ file loader +geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT | |**1**| generate various 3d geometric shapes +geometry | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | | 2 | various 3D intersection calculations, not lib-ified +geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | | 2 | line & polygon clipping & offsetting +geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | | 2 | polygon triangulation, partitioning +graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | |**1**| blender-style widget rendering +graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | | 2 | quick-n-dirty window text/graphics for Windows +graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator +graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader +graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping +hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** | |**1**| multi-platform tablet input +images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer +images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | |**1**| animated GIF writer +images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** | |**1**| JPEG encoder +images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | |**1**| OpenEXR writer +images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | |**1**| EXR image read/write, uses miniz internally +images | [lodepng](http://lodev.org/lodepng/) | zlib | |**1**| PNG encoder/decoder +images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | |**1**| 1-file SVG parser; 1-file SVG rasterizer +images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader +images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress +math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | |**1**| SIMD vector math +math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | |**1**| approximate transcendental functions optimized for shaders (esp. GCN) +multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | |**1**| cross-platform multithreaded task scheduler +network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** | |**1**| cross-platform socket wrapper +network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | |**1**| lightweight webserver, fork of webby +network | [par_easycurl.h](https://github.com/prideout/par) | MIT | |**1**| curl wrapper +network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | | 2 | non-production-use http server +network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | | 2 | http client requests +network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | | 2 | http server +network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 +parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | |**1**| regular expression matcher +parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer +parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | |**1**| JSON parser +parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | |**1**| C-esque language lexer +parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | | 2 | JSON parser +parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | C++ | 2 | JSON parser +parsing | [parson](https://github.com/kgabis/parson) | MIT | C | 2 | JSON parser and serializer +parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file regex (also binary tree, etc) +profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer +profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally +scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ +strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** | |**1**| utf8 string library +strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** | |**1**| string interning +strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder +strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** | C |**1**| dynamic strings for C +tests | [utest](https://github.com/evolutional/utest) | MIT | |**1**| unit testing +tests | [catch](https://github.com/philsquared/Catch) | Boost | |**1**| unit testing +tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | |**1**| unit testing +tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions in C++ +user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | | 9 | an immediate-mode GUI formerly named "ImGui" +_misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** | **public domain** | |**1**| allocate/deallocate small integer IDs efficiently +_misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** | C++ |**1**| flexible logging for C++ +_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| C++ typesafe printf +_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | | 2 | cross-platform debug util libraries +_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | | 2 | extract English word stems +_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | | 2 | compute edit distance between two strings + +There are also these XML libraries, but if you're using XML, shame on you: + +- parsing: [tinyxml2](https://github.com/leethomason/tinyxml2): XML - parsing: [pugixml](http://pugixml.org/): XML (MIT license) -There are some libraries that are just _so_ awesome that even though they use more -than two files we're going to give them special dispensation to appear in their own -little list here. If you're a crazy purist, be warned, but otherwise, enjoy! - Also you might be interested in other related, but different lists: - [clib](https://github.com/clibs/clib/wiki/Packages): list of (mostly) small single C functions (licenses not listed) From 448275b1945da68ae6e42ed6155574ecf6877119 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 05:58:11 -0800 Subject: [PATCH 232/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index cea95ff..94fddf3 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -12,7 +12,7 @@ many libraries, and the benefit of the doubt is given for boldfacing.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- | -------------------- | --- | --- | ----------- -AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | | 2 | pathfinding with A* +AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | |**1**| IMA-ADPCM audio decoder compression | [miniz.c](https://github.com/richgel999/miniz) |**public domain**| C | 2 | compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | | 2 | fast but larger LZ compression From 825e97b680e837d206e95611ca1b677889038a71 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 06:49:31 -0800 Subject: [PATCH 233/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 94fddf3..b1e4dd6 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -85,7 +85,7 @@ user interface | [dear imgui](https://github.com/ocornut/imgui) _misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** | **public domain** | |**1**| allocate/deallocate small integer IDs efficiently _misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** | C++ |**1**| flexible logging for C++ _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| C++ typesafe printf -_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | | 2 | cross-platform debug util libraries +_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib |**C**| 2 | cross-platform debug util libraries _misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | | 2 | extract English word stems _misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | | 2 | compute edit distance between two strings From c26f400e6f8e62154cd99d0663d68bb821ddc272 Mon Sep 17 00:00:00 2001 From: Lewis Van Winkle Date: Sat, 23 Jan 2016 10:25:23 -0600 Subject: [PATCH 234/522] Added minctest and tinyexpr. --- docs/other_libs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index b1e4dd6..659f766 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -53,6 +53,7 @@ images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | |**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | |**1**| approximate transcendental functions optimized for shaders (esp. GCN) +math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | |**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** | |**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | |**1**| lightweight webserver, fork of webby @@ -77,6 +78,7 @@ strings |**[utf8](https://github.com/sheredom/utf8.h)** strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** | |**1**| string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** | C |**1**| dynamic strings for C +tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing tests | [utest](https://github.com/evolutional/utest) | MIT | |**1**| unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | |**1**| unit testing tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | |**1**| unit testing From 9c8762a1565b50dedbf2fec3834d91e6adc9a2c9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 08:44:27 -0800 Subject: [PATCH 235/522] update other_libs.md --- docs/other_libs.md | 22 +++++++++++++--------- tests/stb.dsp | 4 ++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index cea95ff..97a4a8c 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -6,15 +6,19 @@ People have told me about quite a few of these. However, I haven't used most of and can't comment on their quality. (If you use them and aren't their author, feel free to tell me about their quality. -**Public domain single-file libraries usable from C are in bold.** Other libraries are either non-public domain, -or two files, or only usable from C++, or all three. (As of this writing, the usability-from-C is unknown for -many libraries, and the benefit of the doubt is given for boldfacing.) +**Public domain single-file libraries usable from C and C++ are in bold.** Other libraries are either non-public domain, +or two files, or only usable from C++, or all three. + +For the API column, "C" means C only, "C++" means C++ only, and "**C**" means C/C++; +I use this notation to keep the column a little narrower than "C/C++" would be. +(As of this writing, the API is unknown for many libraries, and the benefit of the doubt +is given for boldfacing.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- | -------------------- | --- | --- | ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | | 2 | pathfinding with A* audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | |**1**| IMA-ADPCM audio decoder -compression | [miniz.c](https://github.com/richgel999/miniz) |**public domain**| C | 2 | compression,decompression, zip file, png writing +compression | [miniz.c](https://github.com/richgel999/miniz) |**public domain**|**C**| 2 | compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | | 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT | | 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD | | 2 | fast but larger LZ compression @@ -67,7 +71,7 @@ parsing | [mm_json.h](https://github.com/vurtun/mmx) parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | |**1**| C-esque language lexer parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | | 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | C++ | 2 | JSON parser -parsing | [parson](https://github.com/kgabis/parson) | MIT | C | 2 | JSON parser and serializer +parsing | [parson](https://github.com/kgabis/parson) | MIT |**C**| 2 | JSON parser and serializer parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally @@ -76,15 +80,15 @@ strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** | |**1**| utf8 string library strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** | |**1**| string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder -strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** | C |**1**| dynamic strings for C +strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |**C**|**1**| dynamic strings tests | [utest](https://github.com/evolutional/utest) | MIT | |**1**| unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | |**1**| unit testing tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | |**1**| unit testing -tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions in C++ +tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | | 9 | an immediate-mode GUI formerly named "ImGui" _misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** | **public domain** | |**1**| allocate/deallocate small integer IDs efficiently -_misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** | C++ |**1**| flexible logging for C++ -_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| C++ typesafe printf +_misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** | C++ |**1**| flexible logging +_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf _misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib | | 2 | cross-platform debug util libraries _misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | | 2 | extract English word stems _misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | | 2 | compute edit distance between two strings diff --git a/tests/stb.dsp b/tests/stb.dsp index 20f341b..68c1806 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -86,6 +86,10 @@ LINK32=link.exe # Name "stb - Win32 Debug" # Begin Source File +SOURCE=..\docs\other_libs.md +# End Source File +# Begin Source File + SOURCE=.\stb.c # End Source File # Begin Source File From 6308d725f40132a4278edf15a8a50dd270adab51 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 08:55:28 -0800 Subject: [PATCH 236/522] update other_libs.md --- docs/other_libs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index fb35808..0db5f35 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -45,7 +45,7 @@ graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping -hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** | |**1**| multi-platform tablet input +hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |**C**|**1**| multi-platform tablet input images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | |**1**| animated GIF writer images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** | |**1**| JPEG encoder @@ -92,8 +92,8 @@ _misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** _misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf _misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib |**C**| 2 | cross-platform debug util libraries -_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | | 2 | extract English word stems -_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | | 2 | compute edit distance between two strings +_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | C | 2 | extract English word stems +_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | C | 2 | compute edit distance between two strings There are also these XML libraries, but if you're using XML, shame on you: From d9552a9c510629f178454b3175f847def5316457 Mon Sep 17 00:00:00 2001 From: Mayank Lahiri Date: Sat, 23 Jan 2016 09:11:31 -0800 Subject: [PATCH 237/522] Add easy_exif to other_libs.md EasyEXIF is a tiny, lightweight C++ library that parses basic information out of JPEG files. It uses only the std::string library and is otherwise pure C++. You pass it the binary contents of a JPEG file, and it parses out a few of the most important EXIF fields for you. --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0db5f35..76e837d 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -55,6 +55,7 @@ images | [lodepng](http://lodev.org/lodepng/) images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | |**1**| 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress +images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 1 | 1-file EXIF metadata extractor for JPEG images math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | |**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | |**1**| approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings From d1770130614dc4106f40fec168877147d61fe966 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 09:21:29 -0800 Subject: [PATCH 238/522] add submission notes, cleanup easyexif --- docs/other_libs.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 76e837d..096ef5e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -2,18 +2,26 @@ In addition to all of [my libraries](https://github.com/nothings/stb), there are other, similar libraries. -People have told me about quite a few of these. However, I haven't used most of these libraries -and can't comment on their quality. (If you use them and aren't their author, feel -free to tell me about their quality. +People have told me about quite a few of these. However, I haven't used most of +these libraries and can't comment on their quality. (If you use them and aren't +their author, feel free to tell me about their quality. **Public domain single-file libraries usable from C and C++ are in bold.** Other libraries are either non-public domain, -or two files, or only usable from C++, or all three. +or two files, or only usable from C++, or all three. Libraries of more than two +files are mostly forbidden. For the API column, "C" means C only, "C++" means C++ only, and "**C**" means C/C++; I use this notation to keep the column a little narrower than "C/C++" would be. (As of this writing, the API is unknown for many libraries, and the benefit of the doubt is given for boldfacing.) +Submissions: I accept submissions (as issues or as pull requests). Please note that every +file that must be included in the project counts; a header and a source file is 2 files, +but a header file, source file, and LICENSE (if the license isn't in the source file) is 3 +files, and won't be accepted, because it's not 2 files. But actually 'LICENSE' is a problem +for just dropping the library in a source tree anyway, since it's not scoped to just the +library, so authors are encouraged to include the license in the source file. + category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- | -------------------- | --- | --- | ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* @@ -55,7 +63,7 @@ images | [lodepng](http://lodev.org/lodepng/) images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | |**1**| 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress -images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 1 | 1-file EXIF metadata extractor for JPEG images +images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | |**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | |**1**| approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings From 9fe0dc93a425defcc4e09be6e0bcff68ba8cb983 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 09:30:37 -0800 Subject: [PATCH 239/522] other_libs gets more guidelines --- docs/other_libs.md | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 096ef5e..4d8750e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -2,26 +2,46 @@ In addition to all of [my libraries](https://github.com/nothings/stb), there are other, similar libraries. -People have told me about quite a few of these. However, I haven't used most of -these libraries and can't comment on their quality. (If you use them and aren't -their author, feel free to tell me about their quality. +The following list is a list of small, easy-to-integrate, portable libraries +which are usable from C and/or C++, and should be able to be compiled on both +32-bit and 64-bit platforms. -**Public domain single-file libraries usable from C and C++ are in bold.** Other libraries are either non-public domain, -or two files, or only usable from C++, or all three. Libraries of more than two -files are mostly forbidden. +### Rules + +- Libraries must be usable from C or C++, ideally both +- Libraries should be usable from more than one platform (ideally, all major desktops and/or all major mobile) +- Libraries should compile and work on both 32-bit and 64-bit platforms +- Libraries should use at most two files + +Exceptions will be allowed for good reasons. + +### New libraries and corrections + +Submissions of new libraries: I accept submissions (as issues or as pull requests). Please +note that every file that must be included in a user's project counts; a header and a source +file is 2 files, but a header file, source file, and LICENSE (if the license isn't in the +source file) is 3 files, and won't be accepted, because it's not 2 files. But actually +'LICENSE' is a problem for just dropping the library in a source tree anyway, since it's +not scoped to just the library, so library authors are encouraged to include the license in the +source file and not require a separate LICENSE. + +Corrections: if information for a library below is wrong, please send a correction as an +issue, pull request, or email. Note that if the list indicates a library works from both +C/C++, but it doesn't, this could be an error in the list or it could be a bug in the +library. If you find a library doesn't work in 32-bit or 64-bit, the library should be +removed from this list, unless it's a bug in the library. + +## Library listing + +**Public domain single-file libraries usable from C and C++ are in bold.** Other +libraries are either non-public domain, or two files, or only usable from C++, or +all three. Libraries of more than two files are mostly forbidden. For the API column, "C" means C only, "C++" means C++ only, and "**C**" means C/C++; I use this notation to keep the column a little narrower than "C/C++" would be. (As of this writing, the API is unknown for many libraries, and the benefit of the doubt is given for boldfacing.) -Submissions: I accept submissions (as issues or as pull requests). Please note that every -file that must be included in the project counts; a header and a source file is 2 files, -but a header file, source file, and LICENSE (if the license isn't in the source file) is 3 -files, and won't be accepted, because it's not 2 files. But actually 'LICENSE' is a problem -for just dropping the library in a source tree anyway, since it's not scoped to just the -library, so authors are encouraged to include the license in the source file. - category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- | -------------------- | --- | --- | ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* From 4aff4632f3ab811e71c44301d94f4e75f4707cfe Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 09:37:32 -0800 Subject: [PATCH 240/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 4d8750e..562067c 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -73,6 +73,7 @@ graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping +graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ | 1 | API-agnostic immediate-mode debug rendering hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |**C**|**1**| multi-platform tablet input images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | |**1**| animated GIF writer From 143834ed420400514d706e6eaecc78a52f55d372 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 09:38:32 -0800 Subject: [PATCH 241/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 562067c..4d37f64 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -73,7 +73,7 @@ graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping -graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ | 1 | API-agnostic immediate-mode debug rendering +graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |**C**|**1**| multi-platform tablet input images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | |**1**| animated GIF writer From 3a4e6485b45f35a86f783d3db0320624c4dd2d6c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 09:39:51 -0800 Subject: [PATCH 242/522] Update other_libs.md --- docs/other_libs.md | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 4d37f64..ce8b14a 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -17,19 +17,7 @@ Exceptions will be allowed for good reasons. ### New libraries and corrections -Submissions of new libraries: I accept submissions (as issues or as pull requests). Please -note that every file that must be included in a user's project counts; a header and a source -file is 2 files, but a header file, source file, and LICENSE (if the license isn't in the -source file) is 3 files, and won't be accepted, because it's not 2 files. But actually -'LICENSE' is a problem for just dropping the library in a source tree anyway, since it's -not scoped to just the library, so library authors are encouraged to include the license in the -source file and not require a separate LICENSE. - -Corrections: if information for a library below is wrong, please send a correction as an -issue, pull request, or email. Note that if the list indicates a library works from both -C/C++, but it doesn't, this could be an error in the list or it could be a bug in the -library. If you find a library doesn't work in 32-bit or 64-bit, the library should be -removed from this list, unless it's a bug in the library. +See discussion after the list. ## Library listing @@ -134,6 +122,22 @@ Also you might be interested in other related, but different lists: - [clib](https://github.com/clibs/clib/wiki/Packages): list of (mostly) small single C functions (licenses not listed) +## New libraries and corrections + +Submissions of new libraries: I accept submissions (as issues or as pull requests). Please +note that every file that must be included in a user's project counts; a header and a source +file is 2 files, but a header file, source file, and LICENSE (if the license isn't in the +source file) is 3 files, and won't be accepted, because it's not 2 files. But actually +'LICENSE' is a problem for just dropping the library in a source tree anyway, since it's +not scoped to just the library, so library authors are encouraged to include the license in the +source file and not require a separate LICENSE. + +Corrections: if information for a library below is wrong, please send a correction as an +issue, pull request, or email. Note that if the list indicates a library works from both +C/C++, but it doesn't, this could be an error in the list or it could be a bug in the +library. If you find a library doesn't work in 32-bit or 64-bit, the library should be +removed from this list, unless it's a bug in the library. + ## *List FAQ* ### Can I link directly to this list? From c2a4ff554d45209511f5102f29c8d7fa5b8a2236 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 09:40:42 -0800 Subject: [PATCH 243/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index ce8b14a..afa96b5 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -22,7 +22,7 @@ See discussion after the list. ## Library listing **Public domain single-file libraries usable from C and C++ are in bold.** Other -libraries are either non-public domain, or two files, or only usable from C++, or +libraries are either non-public domain, or two files, or not usable from both C and C++, or all three. Libraries of more than two files are mostly forbidden. For the API column, "C" means C only, "C++" means C++ only, and "**C**" means C/C++; From 97b614a080a4345f99fe65afd2cdeeb7662edb64 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 10:14:43 -0800 Subject: [PATCH 244/522] Update other_libs.md --- docs/other_libs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index afa96b5..185fad1 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -34,7 +34,7 @@ category | library ----------------- | --------------------------------------------------------------------- | -------------------- | --- | --- | ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | |**1**| IMA-ADPCM audio decoder -compression | [miniz.c](https://github.com/richgel999/miniz) |**public domain**|**C**| 2 | compression,decompression, zip file, png writing +compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|**C**|**1**| compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | | 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT | | 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD | | 2 | fast but larger LZ compression @@ -43,7 +43,7 @@ data structures | [klib](http://attractivechaos.github.io/klib/) data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | | 2 | memory-efficient array of elements with non-pow2 bitcount data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) -files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**C**|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** | | 2 | get path/filename of executable or module geometry |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs geometry |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** | |**1**| sobol & stratified sampling sequences @@ -68,8 +68,8 @@ images |**[gif.h](https://github.com/ginsweater/gif-h)** images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** | |**1**| JPEG encoder images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | |**1**| OpenEXR writer images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | |**1**| EXR image read/write, uses miniz internally -images | [lodepng](http://lodev.org/lodepng/) | zlib | |**1**| PNG encoder/decoder -images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib | |**1**| 1-file SVG parser; 1-file SVG rasterizer +images | [lodepng](http://lodev.org/lodepng/) | zlib |**C**|**1**| PNG encoder/decoder +images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |**C**|**1**| 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images From 97a7c1ba9b70ccf0175c28e3097ee584c07f2f86 Mon Sep 17 00:00:00 2001 From: Danyil Bohdan Date: Sat, 23 Jan 2016 20:14:44 +0200 Subject: [PATCH 245/522] other_libs.md: Add LIL --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index afa96b5..f27c714 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -94,6 +94,7 @@ parsing | [parson](https://github.com/kgabis/parson) parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally +scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |**C**| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** | |**1**| utf8 string library From 6a5590e11e5331c6f218a82f212f54469fac4e0b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 10:16:34 -0800 Subject: [PATCH 246/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 185fad1..013fd8c 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -31,7 +31,7 @@ I use this notation to keep the column a little narrower than "C/C++" would be. is given for boldfacing.) category | library | license | API |files| description ------------------ | --------------------------------------------------------------------- | -------------------- | --- | --- | ----------- +----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | |**1**| IMA-ADPCM audio decoder compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|**C**|**1**| compression,decompression, zip file, png writing @@ -39,7 +39,7 @@ compression | [lz4](https://github.com/Cyan4973/lz4) compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT | | 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD | | 2 | fast but larger LZ compression crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | | 2 | high-quality tiny cryptography library -data structures | [klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc +data structures|[klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | | 2 | memory-efficient array of elements with non-pow2 bitcount data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) From 02b90e8fb5730d34e19f78f27be2e8ce2173e5e6 Mon Sep 17 00:00:00 2001 From: Danyil Bohdan Date: Sat, 23 Jan 2016 23:02:10 +0200 Subject: [PATCH 247/522] other_libs.md: Add Picol --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index f27c714..1aabb29 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -96,6 +96,7 @@ profiling | [Remotery](https://github.com/Celtoys/Remotery) profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |**C**| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ +scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |**C**| 2 | interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** | |**1**| utf8 string library strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** | |**1**| string interning From b0b3c2633d58c2b01d084afd5cc7fb8686079079 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 14:39:54 -0800 Subject: [PATCH 248/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index ae1c2e1..85ac707 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -83,7 +83,7 @@ network | [par_easycurl.h](https://github.com/prideout/par) network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | | 2 | non-production-use http server network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | | 2 | http client requests network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | | 2 | http server -network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 +network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | C++ | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | |**1**| regular expression matcher parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | |**1**| JSON parser From 1de24920028909bd18f6a0952d225fa1dccce5c3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 23 Jan 2016 23:44:21 -0800 Subject: [PATCH 249/522] Update other_libs.md --- docs/other_libs.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 85ac707..6e2bc27 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -45,17 +45,18 @@ data structures | [PackedArray](https://github.com/gpakosz/PackedArray) data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**C**|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** | | 2 | get path/filename of executable or module -geometry |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs -geometry |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** | |**1**| sobol & stratified sampling sequences -geometry | [sdf.h](https://github.com/memononen/SDF) | MIT | |**1**| compute signed-distance field from antialiased image -geometry | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | |**1**| build KD trees for point clouds -geometry | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | |**1**| find voronoi regions on float/double data -geometry | [par_msquares](https://github.com/prideout/par) | MIT | |**1**| convert (binarized) image to triangles -geometry | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT | |**1**| OBJ file loader -geometry | [par_shapes](http://github.prideout.net/shapes/) | MIT | |**1**| generate various 3d geometric shapes -geometry | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | | 2 | various 3D intersection calculations, not lib-ified -geometry | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | | 2 | line & polygon clipping & offsetting -geometry | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | | 2 | polygon triangulation, partitioning +geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT | |**1**| OBJ file loader +geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader +geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs +geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** | |**1**| sobol & stratified sampling sequences +geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT | |**1**| compute signed-distance field from antialiased image +geometry math | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | |**1**| build KD trees for point clouds +geometry math | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | |**1**| find voronoi regions on float/double data +geometry math | [par_msquares](https://github.com/prideout/par) | MIT | |**1**| convert (binarized) image to triangles +geometry math | [par_shapes](http://github.prideout.net/shapes/) | MIT | |**1**| generate various 3d geometric shapes +geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | | 2 | various 3D intersection calculations, not lib-ified +geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | | 2 | line & polygon clipping & offsetting +geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | | 2 | polygon triangulation, partitioning graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | |**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | | 2 | quick-n-dirty window text/graphics for Windows graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator From fc5009027d76e5f8bfa57375835a4001879db311 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 05:31:12 -0800 Subject: [PATCH 250/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 6e2bc27..3bf0477 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -41,10 +41,10 @@ compression | [pithy](https://github.com/johnezang/pithy) crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | | 2 | high-quality tiny cryptography library data structures|[klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc -data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | | 2 | memory-efficient array of elements with non-pow2 bitcount +data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | C | 2 | memory-efficient array of elements with non-pow2 bitcount data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**C**|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** | | 2 | get path/filename of executable or module +files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |**C**| 2 | get path/filename of executable or module geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT | |**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs From 91402d1a0de83d66a4bb6f82d4cac9dca528be84 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 05:36:11 -0800 Subject: [PATCH 251/522] Update other_libs.md --- docs/other_libs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 3bf0477..dcdb937 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -33,11 +33,11 @@ is given for boldfacing.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* -audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT | |**1**| IMA-ADPCM audio decoder +audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |**C**|**1**| IMA-ADPCM audio decoder compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|**C**|**1**| compression,decompression, zip file, png writing -compression | [lz4](https://github.com/Cyan4973/lz4) | BSD | | 2 | fast but larger LZ compression -compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT | | 2 | fast but larger LZ compression -compression | [pithy](https://github.com/johnezang/pithy) | BSD | | 2 | fast but larger LZ compression +compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |**C**| 2 | fast but larger LZ compression +compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT |**C**| 2 | fast but larger LZ compression +compression | [pithy](https://github.com/johnezang/pithy) | BSD |**C**| 2 | fast but larger LZ compression crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | | 2 | high-quality tiny cryptography library data structures|[klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc From 94106a8fdd8938f0ab11794cf597ff41102a015a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 05:38:05 -0800 Subject: [PATCH 252/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index dcdb937..9921704 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -38,7 +38,7 @@ compression |**[miniz.c](https://github.com/richgel999/miniz)** compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |**C**| 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT |**C**| 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD |**C**| 2 | fast but larger LZ compression -crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | | 2 | high-quality tiny cryptography library +crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | C | 2 | high-quality tiny cryptography library data structures|[klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | C | 2 | memory-efficient array of elements with non-pow2 bitcount From cbbd2d053f36c3de26a124b6433810c398319585 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 05:47:02 -0800 Subject: [PATCH 253/522] Update other_libs.md --- docs/other_libs.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 9921704..d3e3c91 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -25,26 +25,27 @@ See discussion after the list. libraries are either non-public domain, or two files, or not usable from both C and C++, or all three. Libraries of more than two files are mostly forbidden. -For the API column, "C" means C only, "C++" means C++ only, and "**C**" means C/C++; -I use this notation to keep the column a little narrower than "C/C++" would be. -(As of this writing, the API is unknown for many libraries, and the benefit of the doubt -is given for boldfacing.) +For the API column, "C" means C only, "C++" means C++ only, and "C/C++C**" means C/C++ usable +from either; even if a library includes a .cpp file it may be usable from C if the header has +the appropriate 'extern "C"' usage, and likewise even if a library includes a .c file it may +be usable from C++ for the same reason. (As of this writing, the API is unknown for many +libraries, and the benefit of the doubt is given for boldfacing.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* -audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |**C**|**1**| IMA-ADPCM audio decoder -compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|**C**|**1**| compression,decompression, zip file, png writing -compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |**C**| 2 | fast but larger LZ compression -compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT |**C**| 2 | fast but larger LZ compression -compression | [pithy](https://github.com/johnezang/pithy) | BSD |**C**| 2 | fast but larger LZ compression +audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder +compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing +compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression +compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT |C/C++| 2 | fast but larger LZ compression +compression | [pithy](https://github.com/johnezang/pithy) | BSD |C/C++| 2 | fast but larger LZ compression crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | C | 2 | high-quality tiny cryptography library data structures|[klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | C | 2 | memory-efficient array of elements with non-pow2 bitcount data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) -files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |**C**|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |**C**| 2 | get path/filename of executable or module +files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT | |**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs @@ -63,14 +64,14 @@ graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering -hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |**C**|**1**| multi-platform tablet input +hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | |**1**| animated GIF writer images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** | |**1**| JPEG encoder images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | |**1**| OpenEXR writer images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | |**1**| EXR image read/write, uses miniz internally -images | [lodepng](http://lodev.org/lodepng/) | zlib |**C**|**1**| PNG encoder/decoder -images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |**C**|**1**| 1-file SVG parser; 1-file SVG rasterizer +images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++|**1**| PNG encoder/decoder +images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images @@ -91,18 +92,18 @@ parsing | [mm_json.h](https://github.com/vurtun/mmx) parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | |**1**| C-esque language lexer parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | | 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | C++ | 2 | JSON parser -parsing | [parson](https://github.com/kgabis/parson) | MIT |**C**| 2 | JSON parser and serializer +parsing | [parson](https://github.com/kgabis/parson) | MIT |C/C++| 2 | JSON parser and serializer parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally -scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |**C**| 2 | interpreter for a Tcl-like scripting language +scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ -scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |**C**| 2 | interpreter for a Tcl-like scripting language +scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++| 2 | interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** | |**1**| utf8 string library strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** | |**1**| string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder -strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |**C**|**1**| dynamic strings +strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings tests | [utest](https://github.com/evolutional/utest) | MIT | |**1**| unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | |**1**| unit testing tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | |**1**| unit testing @@ -112,7 +113,7 @@ user interface | [dear imgui](https://github.com/ocornut/imgui) _misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** | **public domain** | |**1**| allocate/deallocate small integer IDs efficiently _misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf -_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib |**C**| 2 | cross-platform debug util libraries +_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib |C/C++| 2 | cross-platform debug util libraries _misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | C | 2 | extract English word stems _misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | C | 2 | compute edit distance between two strings From e1bc6029b97ca6f4e3c8f84b6ab83af660aa9e9f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 05:48:34 -0800 Subject: [PATCH 254/522] Update other_libs.md --- docs/other_libs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index d3e3c91..38d458f 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -110,8 +110,8 @@ tests | [SPUT](http://www.lingua-systems.com/unit-testing/) tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | | 9 | an immediate-mode GUI formerly named "ImGui" -_misc_ |**[MakeID.h](http://www.humus.name/3D/MakeID.h)** | **public domain** | |**1**| allocate/deallocate small integer IDs efficiently -_misc_ |**[loguru](https://github.com/emilk/loguru)** | **public domain** | C++ |**1**| flexible logging +_misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently +_misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf _misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib |C/C++| 2 | cross-platform debug util libraries _misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | C | 2 | extract English word stems @@ -136,7 +136,7 @@ source file) is 3 files, and won't be accepted, because it's not 2 files. But ac not scoped to just the library, so library authors are encouraged to include the license in the source file and not require a separate LICENSE. -Corrections: if information for a library below is wrong, please send a correction as an +Corrections: if information for a library above is wrong, please send a correction as an issue, pull request, or email. Note that if the list indicates a library works from both C/C++, but it doesn't, this could be an error in the list or it could be a bug in the library. If you find a library doesn't work in 32-bit or 64-bit, the library should be From bb7355f4b1ed1560994d14f0987950af6f80b7d4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 05:50:38 -0800 Subject: [PATCH 255/522] Update other_libs.md --- docs/other_libs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 38d458f..2f4d15b 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -90,7 +90,7 @@ parsing | [SLRE](https://github.com/cesanta/slre) parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | |**1**| JSON parser parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | |**1**| C-esque language lexer -parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** | | 2 | JSON parser +parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** |C/C++| 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | C++ | 2 | JSON parser parsing | [parson](https://github.com/kgabis/parson) | MIT |C/C++| 2 | JSON parser and serializer parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file regex (also binary tree, etc) @@ -100,7 +100,7 @@ scripting | [LIL](http://runtimelegend.com/rep/lil/) scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++| 2 | interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** | |**1**| utf8 string library +strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |C/C++|**1**| utf8 string library strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** | |**1**| string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings @@ -109,7 +109,7 @@ tests | [catch](https://github.com/philsquared/Catch) tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | |**1**| unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing -user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | | 9 | an immediate-mode GUI formerly named "ImGui" +user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++*| 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf From 983630e7b0e18efe07fb125294e2fc17d8a03bf3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 05:59:25 -0800 Subject: [PATCH 256/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2f4d15b..4465f9a 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -101,7 +101,7 @@ scripting | [lualite](https://github.com/janezz55/lualite/) scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++| 2 | interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |C/C++|**1**| utf8 string library -strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** | |**1**| string interning +strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** |C/C++|**1**| string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings tests | [utest](https://github.com/evolutional/utest) | MIT | |**1**| unit testing From 420c68ac83e806c3b58dff3606613426c15b91b3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 06:07:23 -0800 Subject: [PATCH 257/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 4465f9a..b01f6f9 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -41,7 +41,7 @@ compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#sv compression | [pithy](https://github.com/johnezang/pithy) | BSD |C/C++| 2 | fast but larger LZ compression crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | C | 2 | high-quality tiny cryptography library data structures|[klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc -data structures | [uthash](https://github.com/troydhanson/uthash) | BSD | | 2 | several 1-header, 1-license-file libs: generic hash, list, etc +data structures | [uthash](https://github.com/troydhanson/uthash) | BSD |C/C++| 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | C | 2 | memory-efficient array of elements with non-pow2 bitcount data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings From 7a889d272a65322ed5dd514018ff645507918b4d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 06:16:48 -0800 Subject: [PATCH 258/522] Update other_libs.md --- docs/other_libs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index b01f6f9..fc8b0b4 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -53,8 +53,8 @@ geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-ju geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT | |**1**| compute signed-distance field from antialiased image geometry math | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | |**1**| build KD trees for point clouds geometry math | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | |**1**| find voronoi regions on float/double data -geometry math | [par_msquares](https://github.com/prideout/par) | MIT | |**1**| convert (binarized) image to triangles -geometry math | [par_shapes](http://github.prideout.net/shapes/) | MIT | |**1**| generate various 3d geometric shapes +geometry math | [par_msquares](https://github.com/prideout/par) | MIT |C/C++|**1**| convert (binarized) image to triangles +geometry math | [par_shapes](http://github.prideout.net/shapes/) | MIT |C/C++|**1**| generate various 3d geometric shapes geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | | 2 | various 3D intersection calculations, not lib-ified geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | | 2 | line & polygon clipping & offsetting geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | | 2 | polygon triangulation, partitioning @@ -81,7 +81,7 @@ math | [TinyExpr](https://github.com/codeplea/tinyexpr) multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | |**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** | |**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | |**1**| lightweight webserver, fork of webby -network | [par_easycurl.h](https://github.com/prideout/par) | MIT | |**1**| curl wrapper +network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | | 2 | non-production-use http server network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | | 2 | http client requests network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | | 2 | http server From 4dd8cf9ae83a8b88edb2ec85809b0194d07fa6ce Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 06:25:38 -0800 Subject: [PATCH 259/522] Update other_libs.md --- docs/other_libs.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index fc8b0b4..e7672bf 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -75,12 +75,12 @@ images | [nanoSVG](https://github.com/memononen/nanosvg) images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images -math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD | |**1**| SIMD vector math +math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | |**1**| approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings -multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib | |**1**| cross-platform multithreaded task scheduler +multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** | |**1**| cross-platform socket wrapper -network | [mm_web.h](https://github.com/vurtun/mmx) | BSD | |**1**| lightweight webserver, fork of webby +network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | | 2 | non-production-use http server network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | | 2 | http client requests @@ -88,8 +88,7 @@ network | [mongoose](https://github.com/cesanta/mongoose) network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | C++ | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | |**1**| regular expression matcher parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer -parsing | [mm_json.h](https://github.com/vurtun/mmx) | zlib | |**1**| JSON parser -parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib | |**1**| C-esque language lexer +parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| C-esque language lexer parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** |C/C++| 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | C++ | 2 | JSON parser parsing | [parson](https://github.com/kgabis/parson) | MIT |C/C++| 2 | JSON parser and serializer @@ -99,14 +98,14 @@ profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofil scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++| 2 | interpreter for a Tcl-like scripting language -strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** | |**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings +strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |C/C++|**1**| utf8 string library strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** |C/C++|**1**| string interning strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings -tests | [utest](https://github.com/evolutional/utest) | MIT | |**1**| unit testing -tests | [catch](https://github.com/philsquared/Catch) | Boost | |**1**| unit testing -tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD | |**1**| unit testing +tests | [utest](https://github.com/evolutional/utest) | MIT |C/C++|**1**| unit testing +tests | [catch](https://github.com/philsquared/Catch) | Boost | C++ |**1**| unit testing +tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD |C/C++|**1**| unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++*| 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) From 78befd33e91f18ce8bff7d9aa8a5f59bd6797779 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 06:57:37 -0800 Subject: [PATCH 260/522] Update other_libs.md --- docs/other_libs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index e7672bf..8cbe0d3 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -56,10 +56,10 @@ geometry math | [jc_voronoi](https://github.com/JCash/voronoi) geometry math | [par_msquares](https://github.com/prideout/par) | MIT |C/C++|**1**| convert (binarized) image to triangles geometry math | [par_shapes](http://github.prideout.net/shapes/) | MIT |C/C++|**1**| generate various 3d geometric shapes geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | | 2 | various 3D intersection calculations, not lib-ified -geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | | 2 | line & polygon clipping & offsetting -geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | | 2 | polygon triangulation, partitioning -graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT | |**1**| blender-style widget rendering -graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** | | 2 | quick-n-dirty window text/graphics for Windows +geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | C++ | 2 | line & polygon clipping & offsetting +geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | C++ | 2 | polygon triangulation, partitioning +graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering +graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping @@ -82,7 +82,7 @@ multithreading | [mm_sched.h](https://github.com/vurtun/mmx) network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** | |**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper -network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** | | 2 | non-production-use http server +network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** |C/C++| 2 | non-production-use http server network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | | 2 | http client requests network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | | 2 | http server network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | C++ | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 From 229ebfa4ffb102ce41a9626f1edb4fa6a96f88e5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 07:15:03 -0800 Subject: [PATCH 261/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8cbe0d3..edeec78 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -70,7 +70,7 @@ images |**[gif.h](https://github.com/ginsweater/gif-h)** images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** | |**1**| JPEG encoder images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | |**1**| OpenEXR writer images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | |**1**| EXR image read/write, uses miniz internally -images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++|**1**| PNG encoder/decoder +images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress From 47796836b6e45a020e3948f47b5f87491712cf35 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 08:02:05 -0800 Subject: [PATCH 262/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index edeec78..443c7de 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -76,7 +76,7 @@ images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math -math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | |**1**| approximate transcendental functions optimized for shaders (esp. GCN) +math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** | |**1**| cross-platform socket wrapper From a4a27ea3cdb09a507b39dcf2b405f333b01757ac Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 08:36:59 -0800 Subject: [PATCH 263/522] Update other_libs.md --- docs/other_libs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 443c7de..ded1ba8 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -66,14 +66,14 @@ graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer -images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | |**1**| animated GIF writer -images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** | |**1**| JPEG encoder +images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) +images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | |**1**| OpenEXR writer images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | |**1**| EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader -images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | | 2 | 2-file jpeg compress, 2-file jpeg decompress +images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | C++ | 2 | 2-file jpeg compress, 2-file jpeg decompress images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) From 49f971110f9f2414a472a666e186b01dfcd27800 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 08:39:30 -0800 Subject: [PATCH 264/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index ded1ba8..35675d4 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -68,8 +68,8 @@ hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder -images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | |**1**| OpenEXR writer -images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD | |**1**| EXR image read/write, uses miniz internally +images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | C++ | 2 | OpenEXR writer, needs header file +images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |C/C++|**1**| EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader From f4a878dbf9c38eff173dff2159a808a80636bc79 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 08:40:04 -0800 Subject: [PATCH 265/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 35675d4..84db503 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -68,7 +68,7 @@ hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder -images |**[miniexr](https://github.com/aras-p/miniexr)** | **public domain** | C++ | 2 | OpenEXR writer, needs header file +images | [miniexr](https://github.com/aras-p/miniexr) | **public domain** | C++ | 2 | OpenEXR writer, needs header file images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |C/C++|**1**| EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer From 547c951091eff1495a1d5b4108ce00242b3364a4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 08:43:34 -0800 Subject: [PATCH 266/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 84db503..a802df9 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -46,8 +46,9 @@ data structures | [PackedArray](https://github.com/gpakosz/PackedArray) data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module -geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT | |**1**| OBJ file loader +geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader +geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** | |**1**| sobol & stratified sampling sequences geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT | |**1**| compute signed-distance field from antialiased image @@ -61,7 +62,6 @@ geometry math | [PolyPartition](https://github.com/ivanfratric/polypartitio graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator -graphics (3-D) | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input From ccfca5a5dacb56b6c02698b510bc382be42f566b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 08:45:05 -0800 Subject: [PATCH 267/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index a802df9..8c448d6 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -65,7 +65,7 @@ graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input -images |**[jo_gif.cpp](http://www.jonolick.com/home/gif-writer)** | **public domain** | |**1**| animated GIF writer +images | [jo_gif.cpp](http://www.jonolick.com/home/gif-writer) | **public domain** | C++ |**1**| animated GIF writer (CPP file can also be used as H file) images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder images | [miniexr](https://github.com/aras-p/miniexr) | **public domain** | C++ | 2 | OpenEXR writer, needs header file From b9504633b9cae7d7dc5f3256cd07cbb5d98d3656 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 10:23:34 -0800 Subject: [PATCH 268/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8c448d6..5329799 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -40,10 +40,10 @@ compression | [lz4](https://github.com/Cyan4973/lz4) compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT |C/C++| 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD |C/C++| 2 | fast but larger LZ compression crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | C | 2 | high-quality tiny cryptography library -data structures|[klib](http://attractivechaos.github.io/klib/) | MIT | | 2 | many 2-file libs: hash, sort, b-tree, etc +data structures|[klib](http://attractivechaos.github.io/klib/) | MIT |C/C++| 2 | many 2-file libs: hash, sort, b-tree, etc data structures | [uthash](https://github.com/troydhanson/uthash) | BSD |C/C++| 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | C | 2 | memory-efficient array of elements with non-pow2 bitcount -data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file binary tress (also regex, etc) +data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file binary tress (also regex, etc) files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader From c63e60849705c1be1e676e2f69588b3570e53d73 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 11:42:11 -0800 Subject: [PATCH 269/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 5329799..4fe6282 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -62,7 +62,7 @@ geometry math | [PolyPartition](https://github.com/ivanfratric/polypartitio graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator -graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib | | 2 | compute tangent space for normal mapping +graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib |C/C++| 2 | compute tangent space for normal mapping graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input images | [jo_gif.cpp](http://www.jonolick.com/home/gif-writer) | **public domain** | C++ |**1**| animated GIF writer (CPP file can also be used as H file) From 6e556fe7572e2ab342a2b4dfbd2fa2f91df64569 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 12:08:20 -0800 Subject: [PATCH 270/522] Update other_libs.md --- docs/other_libs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 4fe6282..de3dc7b 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -48,12 +48,12 @@ files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader -geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | |**1**| wavefront OBJ file loader -geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** | |**1**| find voronoi regions on lattice w/ integer inputs -geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** | |**1**| sobol & stratified sampling sequences -geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT | |**1**| compute signed-distance field from antialiased image +geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | C++ |**1**| wavefront OBJ file loader +geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |C/C++|**1**| find voronoi regions on lattice w/ integer inputs +geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |C/C++|**1**| sobol & stratified sampling sequences +geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT |C/C++|**1**| compute signed-distance field from antialiased image geometry math | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | |**1**| build KD trees for point clouds -geometry math | [jc_voronoi](https://github.com/JCash/voronoi) | MIT | |**1**| find voronoi regions on float/double data +geometry math | [jc_voronoi](https://github.com/JCash/voronoi) | MIT |C/C++|**1**| find voronoi regions on float/double data geometry math | [par_msquares](https://github.com/prideout/par) | MIT |C/C++|**1**| convert (binarized) image to triangles geometry math | [par_shapes](http://github.prideout.net/shapes/) | MIT |C/C++|**1**| generate various 3d geometric shapes geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | | 2 | various 3D intersection calculations, not lib-ified From a1169d90d07df9b7cffba977d366a36d79862ead Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 12:22:16 -0800 Subject: [PATCH 271/522] Update other_libs.md --- docs/other_libs.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index de3dc7b..b70c111 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -46,22 +46,23 @@ data structures | [PackedArray](https://github.com/gpakosz/PackedArray) data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file binary tress (also regex, etc) files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module +files & filenames | [noc_file_dialog.h](https://github.com/guillaumechereau/noc) | MIT |C/C++| 1 | file open/save dialogs (Linux/OSX/Windows) geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | C++ |**1**| wavefront OBJ file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |C/C++|**1**| find voronoi regions on lattice w/ integer inputs geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |C/C++|**1**| sobol & stratified sampling sequences geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT |C/C++|**1**| compute signed-distance field from antialiased image -geometry math | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | |**1**| build KD trees for point clouds +geometry math | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | C++ |**1**| build KD trees for point clouds geometry math | [jc_voronoi](https://github.com/JCash/voronoi) | MIT |C/C++|**1**| find voronoi regions on float/double data geometry math | [par_msquares](https://github.com/prideout/par) | MIT |C/C++|**1**| convert (binarized) image to triangles geometry math | [par_shapes](http://github.prideout.net/shapes/) | MIT |C/C++|**1**| generate various 3d geometric shapes -geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** | | 2 | various 3D intersection calculations, not lib-ified +geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** |C/C++| 2 | various 3D intersection calculations, not lib-ified geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | C++ | 2 | line & polygon clipping & offsetting geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | C++ | 2 | polygon triangulation, partitioning graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows -graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | **public domain** | | 2 | procedural graphics generator +graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib |C/C++| 2 | compute tangent space for normal mapping graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input @@ -83,25 +84,25 @@ network |**[zed_net](https://github.com/ZedZull/zed_net)** network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** |C/C++| 2 | non-production-use http server -network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | | 2 | http client requests -network | [mongoose](https://github.com/cesanta/mongoose) | GPLv2 | | 2 | http server +network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | C++ | 2 | http client requests +network | [mongoose](https://github.com/cesanta/mongoose) |_GPLv2_ |C/C++| 2 | http server network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | C++ | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 -parsing | [SLRE](https://github.com/cesanta/slre) | GPLv2 | |**1**| regular expression matcher +parsing | [SLRE](https://github.com/cesanta/slre) |_GPLv2_ | |**1**| regular expression matcher parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| C-esque language lexer parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** |C/C++| 2 | JSON parser parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | C++ | 2 | JSON parser parsing | [parson](https://github.com/kgabis/parson) | MIT |C/C++| 2 | JSON parser and serializer -parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | | 2 | two-file regex (also binary tree, etc) -profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 | | 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer -profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally +parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file regex (also binary tree, etc) +profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 |C/C++| 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer +profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | C++ | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++| 2 | interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |C/C++|**1**| utf8 string library strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** |C/C++|**1**| string interning -strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT | | 2 | fast utf8 decoder +strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT |C/C++| 2 | fast utf8 decoder (need a header file) strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings tests | [utest](https://github.com/evolutional/utest) | MIT |C/C++|**1**| unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | C++ |**1**| unit testing From b8a9e19f867eed1457817db0ea65335271e5119e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 12:23:45 -0800 Subject: [PATCH 272/522] Update other_libs.md --- docs/other_libs.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index b70c111..d52409c 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -28,8 +28,7 @@ all three. Libraries of more than two files are mostly forbidden. For the API column, "C" means C only, "C++" means C++ only, and "C/C++C**" means C/C++ usable from either; even if a library includes a .cpp file it may be usable from C if the header has the appropriate 'extern "C"' usage, and likewise even if a library includes a .c file it may -be usable from C++ for the same reason. (As of this writing, the API is unknown for many -libraries, and the benefit of the doubt is given for boldfacing.) +be usable from C++ for the same reason. category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- @@ -80,14 +79,14 @@ math | [mm_vec.h](https://github.com/vurtun/mmx) math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler -network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** | |**1**| cross-platform socket wrapper +network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** |C/C++| 2 | non-production-use http server network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | C++ | 2 | http client requests network | [mongoose](https://github.com/cesanta/mongoose) |_GPLv2_ |C/C++| 2 | http server network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | C++ | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 -parsing | [SLRE](https://github.com/cesanta/slre) |_GPLv2_ | |**1**| regular expression matcher +parsing | [SLRE](https://github.com/cesanta/slre) |_GPLv2_ |C/C++|**1**| regular expression matcher parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| C-esque language lexer parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** |C/C++| 2 | JSON parser From 1d95d24ae92622e18bef53010ff08b157d87f302 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 12:26:47 -0800 Subject: [PATCH 273/522] Update other_libs.md --- docs/other_libs.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index d52409c..3d7214e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -25,10 +25,12 @@ See discussion after the list. libraries are either non-public domain, or two files, or not usable from both C and C++, or all three. Libraries of more than two files are mostly forbidden. -For the API column, "C" means C only, "C++" means C++ only, and "C/C++C**" means C/C++ usable -from either; even if a library includes a .cpp file it may be usable from C if the header has -the appropriate 'extern "C"' usage, and likewise even if a library includes a .c file it may -be usable from C++ for the same reason. +For the API column, "C" means C only, "C++" means C++ only, and "C/C++" means C/C++ usable +from either; some files may require *building* as C or C++ but still qualify as "C/C++" as +long as the header file uses ~~extern "C"~~ to make it work. (In some cases, a header-file-only +library may compile as both C or C++, but produce an implementation that can only be called from +one or the other, because of a lack of use of ~~extern "C"~~; in this case we still qualify it +as C/C++, as this is not an obstacle to most users.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- From 6fb227061759ae591f14bcb6460deb6d8a942775 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 12:27:51 -0800 Subject: [PATCH 274/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 3d7214e..8f14819 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -27,9 +27,9 @@ all three. Libraries of more than two files are mostly forbidden. For the API column, "C" means C only, "C++" means C++ only, and "C/C++" means C/C++ usable from either; some files may require *building* as C or C++ but still qualify as "C/C++" as -long as the header file uses ~~extern "C"~~ to make it work. (In some cases, a header-file-only +long as the header file uses `extern "C"` to make it work. (In some cases, a header-file-only library may compile as both C or C++, but produce an implementation that can only be called from -one or the other, because of a lack of use of ~~extern "C"~~; in this case we still qualify it +one or the other, because of a lack of use of `extern "C"`; in this case we still qualify it as C/C++, as this is not an obstacle to most users.) category | library | license | API |files| description From 124669a8f5eb7a32248845f4b2e731f86c45864d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 12:28:23 -0800 Subject: [PATCH 275/522] Update other_libs.md --- docs/other_libs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8f14819..2f5cba2 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -29,9 +29,10 @@ For the API column, "C" means C only, "C++" means C++ only, and "C/C++" means C/ from either; some files may require *building* as C or C++ but still qualify as "C/C++" as long as the header file uses `extern "C"` to make it work. (In some cases, a header-file-only library may compile as both C or C++, but produce an implementation that can only be called from -one or the other, because of a lack of use of `extern "C"`; in this case we still qualify it +one or the other, because of a lack of use of `extern "C"`; in this case the table still qualifies it as C/C++, as this is not an obstacle to most users.) + category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* From a78bc165b971f123314896ecda957b82688eb2a7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 26 Jan 2016 12:29:13 -0800 Subject: [PATCH 276/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2f5cba2..3d2f6c8 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -2,7 +2,7 @@ In addition to all of [my libraries](https://github.com/nothings/stb), there are other, similar libraries. -The following list is a list of small, easy-to-integrate, portable libraries +The following is a list of small, easy-to-integrate, portable libraries which are usable from C and/or C++, and should be able to be compiled on both 32-bit and 64-bit platforms. From d35dbc4368b0a341b24ac6e40a0f62cc2cf15310 Mon Sep 17 00:00:00 2001 From: Danyil Bohdan Date: Thu, 28 Jan 2016 16:42:13 +0200 Subject: [PATCH 277/522] other_libs.md: Update Picol --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 3d2f6c8..8e2615f 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -100,7 +100,7 @@ profiling | [Remotery](https://github.com/Celtoys/Remotery) profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | C++ | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ -scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++| 2 | interpreter for a Tcl-like scripting language +scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++|**1**| interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |C/C++|**1**| utf8 string library strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** |C/C++|**1**| string interning From 5e2d0fd777964e05ac4c8a466b6f507dda6a4483 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Tue, 9 Feb 2016 19:40:18 -0800 Subject: [PATCH 278/522] Add support for obtaining the entire kerning table from a font all at once, for use in rendering packed textures offline. --- stb_truetype.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/stb_truetype.h b/stb_truetype.h index bfb1841..ac85727 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -706,6 +706,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); // as above, but takes one or more glyph indices for greater efficiency +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) ////////////////////////////////////////////////////////////////////////////// // @@ -1478,6 +1490,48 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; From 49b65c08734500f5ebabaae9f758ed272e28e18e Mon Sep 17 00:00:00 2001 From: Craig Donner Date: Wed, 10 Feb 2016 14:48:59 -0800 Subject: [PATCH 279/522] Slightly modify the public domain license to keep it in the public domain, but make it clear that even when dedications might not be recognized that the code is still usable. Given that this isn't dual-licensing under a different license, I'm hoping this will be acceptable. --- docs/stb_howto.txt | 4 ++-- docs/why_public_domain.md | 4 ++-- stb.h | 4 ++-- stb_c_lexer.h | 4 ++-- stb_divide.h | 4 ++-- stb_dxt.h | 4 ++-- stb_easy_font.h | 4 ++-- stb_herringbone_wang_tile.h | 4 ++-- stb_image.h | 4 ++-- stb_image_resize.h | 4 ++-- stb_image_write.h | 4 ++-- stb_leakcheck.h | 4 ++-- stb_perlin.h | 4 ++-- stb_rect_pack.h | 4 ++-- stb_textedit.h | 4 ++-- stb_tilemap_editor.h | 4 ++-- stb_truetype.h | 4 ++-- stb_vorbis.c | 4 ++-- stb_voxel_render.h | 4 ++-- stretchy_buffer.h | 4 ++-- 20 files changed, 40 insertions(+), 40 deletions(-) diff --git a/docs/stb_howto.txt b/docs/stb_howto.txt index d0e8ec8..021cd08 100644 --- a/docs/stb_howto.txt +++ b/docs/stb_howto.txt @@ -165,8 +165,8 @@ public domain declarations aren't necessary recognized in the USA and some other locations. For that reason, I recommend a declaration along these lines: -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy // and modify this file as you see fit. I typically place this declaration at the end of the initial diff --git a/docs/why_public_domain.md b/docs/why_public_domain.md index 8636921..af8b199 100644 --- a/docs/why_public_domain.md +++ b/docs/why_public_domain.md @@ -95,8 +95,8 @@ public domain declarations aren't necessary recognized in the USA and some other locations. For that reason, I recommend a declaration along these lines: -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy // and modify this file as you see fit. I typically place this declaration at the end of the initial diff --git a/stb.h b/stb.h index 4b28ae1..00121df 100644 --- a/stb.h +++ b/stb.h @@ -171,8 +171,8 @@ Parenthesized items have since been removed. LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, +This software is dual-licensed to the public domain and under the following +license. You are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. CREDITS diff --git a/stb_c_lexer.h b/stb_c_lexer.h index f6a0035..a4a61c7 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -32,8 +32,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. #ifndef STB_C_LEXER_DEFINITIONS diff --git a/stb_divide.h b/stb_divide.h index 4e35abe..f5322ee 100644 --- a/stb_divide.h +++ b/stb_divide.h @@ -78,8 +78,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. diff --git a/stb_dxt.h b/stb_dxt.h index 418ba65..ba42d3e 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -19,8 +19,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. #ifndef STB_INCLUDE_STB_DXT_H diff --git a/stb_easy_font.h b/stb_easy_font.h index 2fad91f..63025eb 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -67,8 +67,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. // // VERSION HISTORY diff --git a/stb_herringbone_wang_tile.h b/stb_herringbone_wang_tile.h index de7fb20..678e1dc 100644 --- a/stb_herringbone_wang_tile.h +++ b/stb_herringbone_wang_tile.h @@ -3,8 +3,8 @@ == LICENSE ============================== -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, +This software is dual-licensed to the public domain and under the following +license. You are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. == WHAT IT IS =========================== diff --git a/stb_image.h b/stb_image.h index e06f7a1..c577f04 100644 --- a/stb_image.h +++ b/stb_image.h @@ -209,8 +209,8 @@ LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, +This software is dual-licensed to the public domain and under the following +license. You are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. */ diff --git a/stb_image_resize.h b/stb_image_resize.h index 4ce7ddb..6128f58 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -160,8 +160,8 @@ LICENSE - This software is in the public domain. Where that dedication is not - recognized, you are granted a perpetual, irrevocable license to copy, + This software is dual-licensed to the public domain and under the following + license. You are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. TODO diff --git a/stb_image_write.h b/stb_image_write.h index 98fa410..4a1fac9 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -105,8 +105,8 @@ CREDITS: LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, +This software is dual-licensed to the public domain and under the following +license. You are granted a perpetual, irrevocable license to copy, distribute, and modify this file as you see fit. */ diff --git a/stb_leakcheck.h b/stb_leakcheck.h index 7e49fc9..33dfabb 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -1,8 +1,8 @@ // stb_leakcheck.h - v0.2 - quick & dirty malloc leak-checking - public domain // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. #ifdef STB_LEAKCHECK_IMPLEMENTATION diff --git a/stb_perlin.h b/stb_perlin.h index 399e438..cd21dc0 100644 --- a/stb_perlin.h +++ b/stb_perlin.h @@ -3,8 +3,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. // // diff --git a/stb_rect_pack.h b/stb_rect_pack.h index c61de89..af2c00a 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -41,8 +41,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. ////////////////////////////////////////////////////////////////////////////// diff --git a/stb_textedit.h b/stb_textedit.h index 6740b91..3884dd1 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -17,8 +17,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. // // diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index b244c9d..a769205 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -316,8 +316,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. diff --git a/stb_truetype.h b/stb_truetype.h index bfb1841..eae5ad6 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -68,8 +68,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. // // USAGE diff --git a/stb_vorbis.c b/stb_vorbis.c index d54087f..ff8a006 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -9,8 +9,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. // // No warranty for any purpose is expressed or implied by the author (nor diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 29f6fb7..91247cc 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -215,8 +215,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. #ifndef INCLUDE_STB_VOXEL_RENDER_H diff --git a/stretchy_buffer.h b/stretchy_buffer.h index b99c685..7f8734c 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -164,8 +164,8 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, +// This software is dual-licensed to the public domain and under the following +// license. You are granted a perpetual, irrevocable license to copy, // distribute, and modify this file as you see fit. #ifndef STB_STRETCHY_BUFFER_H_INCLUDED From 32b19a6c8b25ef621f9efe23d03d5a552975dce3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 20 Feb 2016 02:15:04 -0800 Subject: [PATCH 280/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8e2615f..2ed7a06 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -62,6 +62,7 @@ geometry math | [par_shapes](http://github.prideout.net/shapes/) geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** |C/C++| 2 | various 3D intersection calculations, not lib-ified geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | C++ | 2 | line & polygon clipping & offsetting geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | C++ | 2 | polygon triangulation, partitioning +geometry math | [Voxelizer](https://github.com/karimnaaji/voxelizer) | MIT |C/C++|**1**| convert triangle mesh to voxel triangle mesh graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator From a4c0a5e88204d799a2db43213c859b36c74850bf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 22 Feb 2016 06:26:21 -0800 Subject: [PATCH 281/522] Update other_libs.md --- docs/other_libs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2ed7a06..def7776 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -49,6 +49,8 @@ data structures | [minilibs](https://github.com/ccxvii/minilibs) files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module files & filenames | [noc_file_dialog.h](https://github.com/guillaumechereau/noc) | MIT |C/C++| 1 | file open/save dialogs (Linux/OSX/Windows) +files & filenames | [dirent](https://github.com/tronkko/dirent) | MIT |C/C++|**1**| dirent for windows: retrieve file & dir info +files & filenames | [TinyDir](https://github.com/cxong/tinydir) | BSD | C |**1**| cross-platform directory reader geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | C++ |**1**| wavefront OBJ file loader From c0774cc7ebe2c55cd5bc2a38cd2e5fd4f5c085c8 Mon Sep 17 00:00:00 2001 From: ReadmeCritic Date: Mon, 22 Feb 2016 08:50:47 -0800 Subject: [PATCH 282/522] Update links for par_shapes, fastlz --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index def7776..8438b7f 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -39,7 +39,7 @@ AI | [micropather](http://www.grinninglizard.com/MicroPather/) audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression -compression | [fastlz](https://code.google.com/p/fastlz/source/browse/#svn%2Ftrunk)| MIT |C/C++| 2 | fast but larger LZ compression +compression | [fastlz](https://code.google.com/archive/p/fastlz/source/default/source) | MIT |C/C++| 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD |C/C++| 2 | fast but larger LZ compression crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | C | 2 | high-quality tiny cryptography library data structures|[klib](http://attractivechaos.github.io/klib/) | MIT |C/C++| 2 | many 2-file libs: hash, sort, b-tree, etc @@ -60,7 +60,7 @@ geometry math | [sdf.h](https://github.com/memononen/SDF) geometry math | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | C++ |**1**| build KD trees for point clouds geometry math | [jc_voronoi](https://github.com/JCash/voronoi) | MIT |C/C++|**1**| find voronoi regions on float/double data geometry math | [par_msquares](https://github.com/prideout/par) | MIT |C/C++|**1**| convert (binarized) image to triangles -geometry math | [par_shapes](http://github.prideout.net/shapes/) | MIT |C/C++|**1**| generate various 3d geometric shapes +geometry math | [par_shapes](http://github.prideout.net/shapes) | MIT |C/C++|**1**| generate various 3d geometric shapes geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** |C/C++| 2 | various 3D intersection calculations, not lib-ified geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | C++ | 2 | line & polygon clipping & offsetting geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | C++ | 2 | polygon triangulation, partitioning From ee6978cb6891632e3fe84264f832140e590b43f0 Mon Sep 17 00:00:00 2001 From: Craig Donner Date: Wed, 10 Feb 2016 14:48:59 -0800 Subject: [PATCH 283/522] Slightly modify the public domain license to keep it in the public domain, but make it clear that even when dedications might not be recognized that the code is still usable. Given that this isn't dual-licensing under a different license, I'm hoping this will be acceptable. --- docs/stb_howto.txt | 6 +++--- docs/why_public_domain.md | 6 +++--- stb.h | 6 +++--- stb_c_lexer.h | 6 +++--- stb_divide.h | 6 +++--- stb_dxt.h | 6 +++--- stb_easy_font.h | 6 +++--- stb_herringbone_wang_tile.h | 6 +++--- stb_image.h | 6 +++--- stb_image_resize.h | 6 +++--- stb_image_write.h | 6 +++--- stb_leakcheck.h | 6 +++--- stb_perlin.h | 6 +++--- stb_rect_pack.h | 6 +++--- stb_textedit.h | 6 +++--- stb_tilemap_editor.h | 6 +++--- stb_truetype.h | 6 +++--- stb_vorbis.c | 6 +++--- stb_voxel_render.h | 6 +++--- stretchy_buffer.h | 6 +++--- 20 files changed, 60 insertions(+), 60 deletions(-) diff --git a/docs/stb_howto.txt b/docs/stb_howto.txt index d0e8ec8..a969b54 100644 --- a/docs/stb_howto.txt +++ b/docs/stb_howto.txt @@ -165,9 +165,9 @@ public domain declarations aren't necessary recognized in the USA and some other locations. For that reason, I recommend a declaration along these lines: -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy -// and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. I typically place this declaration at the end of the initial comment block of the file and just say 'public domain' diff --git a/docs/why_public_domain.md b/docs/why_public_domain.md index 8636921..56cef39 100644 --- a/docs/why_public_domain.md +++ b/docs/why_public_domain.md @@ -95,9 +95,9 @@ public domain declarations aren't necessary recognized in the USA and some other locations. For that reason, I recommend a declaration along these lines: -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy -// and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. I typically place this declaration at the end of the initial comment block of the file and just say 'public domain' diff --git a/stb.h b/stb.h index 4b28ae1..11350ba 100644 --- a/stb.h +++ b/stb.h @@ -171,9 +171,9 @@ Parenthesized items have since been removed. LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. CREDITS diff --git a/stb_c_lexer.h b/stb_c_lexer.h index f6a0035..e91c6c3 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -32,9 +32,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. #ifndef STB_C_LEXER_DEFINITIONS // to change the default parsing rules, copy the following lines diff --git a/stb_divide.h b/stb_divide.h index 4e35abe..d1702f3 100644 --- a/stb_divide.h +++ b/stb_divide.h @@ -78,9 +78,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. #ifndef INCLUDE_STB_DIVIDE_H diff --git a/stb_dxt.h b/stb_dxt.h index 418ba65..0a8b34a 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -19,9 +19,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. #ifndef STB_INCLUDE_STB_DXT_H #define STB_INCLUDE_STB_DXT_H diff --git a/stb_easy_font.h b/stb_easy_font.h index 2fad91f..45bddc9 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -67,9 +67,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // // VERSION HISTORY // diff --git a/stb_herringbone_wang_tile.h b/stb_herringbone_wang_tile.h index de7fb20..ba2cf60 100644 --- a/stb_herringbone_wang_tile.h +++ b/stb_herringbone_wang_tile.h @@ -3,9 +3,9 @@ == LICENSE ============================== -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. == WHAT IT IS =========================== diff --git a/stb_image.h b/stb_image.h index e06f7a1..44e1d56 100644 --- a/stb_image.h +++ b/stb_image.h @@ -209,9 +209,9 @@ LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. */ diff --git a/stb_image_resize.h b/stb_image_resize.h index 4ce7ddb..b0699ba 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -160,9 +160,9 @@ LICENSE - This software is in the public domain. Where that dedication is not - recognized, you are granted a perpetual, irrevocable license to copy, - distribute, and modify this file as you see fit. + This software is dual-licensed to the public domain and under the following + license: you are granted a perpetual, irrevocable license to copy, modify, + publish, and distribute this file as you see fit. TODO Don't decode all of the image data when only processing a partial tile diff --git a/stb_image_write.h b/stb_image_write.h index 98fa410..6b5a455 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -105,9 +105,9 @@ CREDITS: LICENSE -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. +This software is dual-licensed to the public domain and under the following +license: you are granted a perpetual, irrevocable license to copy, modify, +publish, and distribute this file as you see fit. */ diff --git a/stb_leakcheck.h b/stb_leakcheck.h index 7e49fc9..d14c52d 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -1,9 +1,9 @@ // stb_leakcheck.h - v0.2 - quick & dirty malloc leak-checking - public domain // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. #ifdef STB_LEAKCHECK_IMPLEMENTATION #undef STB_LEAKCHECK_IMPLEMENTATION // don't implenment more than once diff --git a/stb_perlin.h b/stb_perlin.h index 399e438..0dac7d9 100644 --- a/stb_perlin.h +++ b/stb_perlin.h @@ -3,9 +3,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // // // to create the implementation, diff --git a/stb_rect_pack.h b/stb_rect_pack.h index c61de89..bd1cfc6 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -41,9 +41,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. ////////////////////////////////////////////////////////////////////////////// // diff --git a/stb_textedit.h b/stb_textedit.h index 6740b91..d932e9a 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -17,9 +17,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // // // DEPENDENCIES diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index b244c9d..cc66dd5 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -316,9 +316,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. diff --git a/stb_truetype.h b/stb_truetype.h index bfb1841..57a38e6 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -68,9 +68,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // // USAGE // diff --git a/stb_vorbis.c b/stb_vorbis.c index d54087f..45540a0 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -9,9 +9,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // // No warranty for any purpose is expressed or implied by the author (nor // by RAD Game Tools). Report bugs and send enhancements to the author. diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 29f6fb7..bfa9902 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -215,9 +215,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. #ifndef INCLUDE_STB_VOXEL_RENDER_H #define INCLUDE_STB_VOXEL_RENDER_H diff --git a/stretchy_buffer.h b/stretchy_buffer.h index b99c685..b9a493c 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -164,9 +164,9 @@ // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. #ifndef STB_STRETCHY_BUFFER_H_INCLUDED #define STB_STRETCHY_BUFFER_H_INCLUDED From 5a00ce39eb97c6323bf69a3e5fb0b7411607dc6d Mon Sep 17 00:00:00 2001 From: Thiago Goulart Date: Wed, 2 Mar 2016 00:50:40 -0800 Subject: [PATCH 284/522] Fix a few warnings when building std_vorbis using Xcode 7.2.1 --- stb_vorbis.c | 97 +++++----------------------------------------------- 1 file changed, 9 insertions(+), 88 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index d54087f..777715d 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1868,85 +1868,6 @@ static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **out return TRUE; } -#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK -static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **outputs, int *c_inter_p, int *p_inter_p, int len, int total_decode) -{ - int c_inter = *c_inter_p; - int p_inter = *p_inter_p; - int i,z, effective = c->dimensions; - - // type 0 is only legal in a scalar context - if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); - - while (total_decode > 0) { - float last = CODEBOOK_ELEMENT_BASE(c); - DECODE_VQ(z,f,c); - - if (z < 0) { - if (!f->bytes_in_seg) - if (f->last_seg) return FALSE; - return error(f, VORBIS_invalid_stream); - } - - // if this will take us off the end of the buffers, stop short! - // we check by computing the length of the virtual interleaved - // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), - // and the length we'll be using (effective) - if (c_inter + p_inter*2 + effective > len * 2) { - effective = len*2 - (p_inter*2 - c_inter); - } - - { - z *= c->dimensions; - if (c->sequence_p) { - // haven't optimized this case because I don't have any examples - for (i=0; i < effective; ++i) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == 2) { c_inter = 0; ++p_inter; } - last = val; - } - } else { - i=0; - if (c_inter == 1 && i < effective) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - c_inter = 0; ++p_inter; - ++i; - } - { - float *z0 = outputs[0]; - float *z1 = outputs[1]; - for (; i+1 < effective;) { - float v0 = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - float v1 = CODEBOOK_ELEMENT_FAST(c,z+i+1) + last; - if (z0) - z0[p_inter] += v0; - if (z1) - z1[p_inter] += v1; - ++p_inter; - i += 2; - } - } - if (i < effective) { - float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; - if (outputs[c_inter]) - outputs[c_inter][p_inter] += val; - if (++c_inter == 2) { c_inter = 0; ++p_inter; } - } - } - } - - total_decode -= effective; - } - *c_inter_p = c_inter; - *p_inter_p = p_inter; - return TRUE; -} -#endif - static int predict_point(int x, int x0, int x1, int y0, int y1) { int dy = y1 - y0; @@ -4429,7 +4350,7 @@ int stb_vorbis_decode_frame_pushdata( while (get8_packet(f) != EOP) if (f->eof) break; *samples = 0; - return f->stream - data; + return (int) (f->stream - data); } if (error == VORBIS_continued_packet_flag_invalid) { if (f->previous_length == 0) { @@ -4439,7 +4360,7 @@ int stb_vorbis_decode_frame_pushdata( while (get8_packet(f) != EOP) if (f->eof) break; *samples = 0; - return f->stream - data; + return (int) (f->stream - data); } } // if we get an error while parsing, what to do? @@ -4459,7 +4380,7 @@ int stb_vorbis_decode_frame_pushdata( if (channels) *channels = f->channels; *samples = len; *output = f->outputs; - return f->stream - data; + return (int) (f->stream - data); } stb_vorbis *stb_vorbis_open_pushdata( @@ -4482,7 +4403,7 @@ stb_vorbis *stb_vorbis_open_pushdata( f = vorbis_alloc(&p); if (f) { *f = p; - *data_used = f->stream - data; + *data_used = (int) (f->stream - data); *error = 0; return f; } else { @@ -4497,9 +4418,9 @@ unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) #ifndef STB_VORBIS_NO_PUSHDATA_API if (f->push_mode) return 0; #endif - if (USE_MEMORY(f)) return f->stream - f->stream_start; + if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start); #ifndef STB_VORBIS_NO_STDIO - return ftell(f->f) - f->f_start; + return (unsigned int) (ftell(f->f) - f->f_start); #endif } @@ -4995,7 +4916,7 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er stb_vorbis *f, p; vorbis_init(&p, alloc); p.f = file; - p.f_start = ftell(file); + p.f_start = (uint32) ftell(file); p.stream_len = length; p.close_on_free = close_on_free; if (start_decoder(&p)) { @@ -5014,9 +4935,9 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) { unsigned int len, start; - start = ftell(file); + start = (unsigned int) ftell(file); fseek(file, 0, SEEK_END); - len = ftell(file) - start; + len = (unsigned int) (ftell(file) - start); fseek(file, start, SEEK_SET); return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); } From 291ad22e84d18bea400873adc991b2d324bc7cda Mon Sep 17 00:00:00 2001 From: Thatcher Ulrich Date: Wed, 2 Mar 2016 15:31:07 -0500 Subject: [PATCH 285/522] Replace large stack allocations with dynamic allocations. --- stb_image.h | 39 ++++++++++++++++++++++----------------- stb_image_write.h | 3 ++- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/stb_image.h b/stb_image.h index e06f7a1..a128a5e 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3408,10 +3408,13 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) { - stbi__jpeg j; - j.s = s; - stbi__setup_jpeg(&j); - return load_jpeg_image(&j, x,y,comp,req_comp); + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; } static int stbi__jpeg_test(stbi__context *s) @@ -5649,13 +5652,15 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) { - stbi__gif g; - if (!stbi__gif_header(s, &g, comp, 1)) { + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); stbi__rewind( s ); return 0; } - if (x) *x = g.w; - if (y) *y = g.h; + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); return 1; } @@ -5908,20 +5913,20 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi_uc *u = 0; - stbi__gif g; - memset(&g, 0, sizeof(g)); + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + memset(g, 0, sizeof(*g)); - u = stbi__gif_load_next(s, &g, comp, req_comp); + u = stbi__gif_load_next(s, g, comp, req_comp); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { - *x = g.w; - *y = g.h; + *x = g->w; + *y = g->h; if (req_comp && req_comp != 4) - u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + u = stbi__convert_format(u, 4, req_comp, g->w, g->h); } - else if (g.out) - STBI_FREE(g.out); - + else if (g->out) + STBI_FREE(g->out); + STBI_FREE(g); return u; } diff --git a/stb_image_write.h b/stb_image_write.h index 98fa410..0935dc1 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -736,7 +736,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l unsigned int bitbuf=0; int i,j, bitcount=0; unsigned char *out = NULL; - unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack! + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); if (quality < 5) quality = 5; stbiw__sbpush(out, 0x78); // DEFLATE 32K window @@ -808,6 +808,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l for (i=0; i < stbiw__ZHASH; ++i) (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); { // compute adler32 on input From 7e1ee2d386b7ec334cf01660ced88426e5188a40 Mon Sep 17 00:00:00 2001 From: Thatcher Ulrich Date: Wed, 2 Mar 2016 15:56:53 -0500 Subject: [PATCH 286/522] Allocate large structure using malloc instead of stack. --- stb_image.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index a128a5e..08d2f84 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3442,9 +3442,12 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) { - stbi__jpeg j; - j.s = s; - return stbi__jpeg_info_raw(&j, x, y, comp); + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; } #endif From b9bc6148d4c00da9b6a99a825ca6cf3b19cd06b6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 7 Mar 2016 20:44:29 -0800 Subject: [PATCH 287/522] linalg.h --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8438b7f..fb1abc1 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -84,6 +84,7 @@ images | [easyexif](https://github.com/mayanklahiri/easyexif) math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings +math | [linalg.h][(https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby From 8aa9afb30e6aeb129235829c5e0ed41b6562ea37 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 7 Mar 2016 20:44:59 -0800 Subject: [PATCH 288/522] typo --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index fb1abc1..8e52c5e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -84,7 +84,7 @@ images | [easyexif](https://github.com/mayanklahiri/easyexif) math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings -math | [linalg.h][(https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math +math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby From 46b64eb878e7cb8c953dafc021fe5d036b4f6101 Mon Sep 17 00:00:00 2001 From: Sergey Kosarevsky Date: Thu, 10 Mar 2016 19:49:38 +0100 Subject: [PATCH 289/522] Added PoissonGenerator.h --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8e52c5e..209b563 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -85,6 +85,7 @@ math | [mm_vec.h](https://github.com/vurtun/mmx) math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math +math | [PoissonGenerator.h](https://github.com/corporateshark/poisson-disk-generator) | MIT | C++ |**1**| Poisson disk points generator (disk or rect) multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby From 94f2ceac1595d7297d76a734fcd1bc111622f6dd Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Sat, 12 Mar 2016 01:55:59 +1300 Subject: [PATCH 290/522] Fix typo in stbi__parse_uncompressed_block --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index e06f7a1..289d804 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3732,7 +3732,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) return 1; } -static int stbi__parse_uncomperssed_block(stbi__zbuf *a) +static int stbi__parse_uncompressed_block(stbi__zbuf *a) { stbi_uc header[4]; int len,nlen,k; @@ -3798,7 +3798,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) final = stbi__zreceive(a,1); type = stbi__zreceive(a,2); if (type == 0) { - if (!stbi__parse_uncomperssed_block(a)) return 0; + if (!stbi__parse_uncompressed_block(a)) return 0; } else if (type == 3) { return 0; } else { From 0985e893350d4a599d36de7da94e6bf4101ecdd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Thu, 17 Mar 2016 09:23:45 +0100 Subject: [PATCH 291/522] stb_vorbis: Fix memory leak in decode_residue() and inverse_mdct() when redefining temp_alloc() and temp_free() temp_alloc() and temp_free() are documented as customization points in section "MEMORY ALLOCATION" (stb_vorbis.c:81). However, in decode_residue() and inverse_mdct() (via temp_block_array() and temp_alloc() respectively), stb_vorbis allocates temporary memory but does not call temp_free() when finished. It does call temp_alloc_restore() though, but there is no sane way to provide an implementation thereof when using a malloc()/free()-like allocation backend. Adding calls to temp_free() before the respective calls to temp_alloc_restore() is safe, because in case of a non-empty temp_alloc_restore() implementation, temp_free() would simply be implemented empty (the current implementation of temp_*() is fine in this regard). That way, all possible temporary memory allocation schemes (i.e. alloca(), custom provided alloc_buffer, malloc()) are handled properly. Add the appropriate temp_free() calls. --- stb_vorbis.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stb_vorbis.c b/stb_vorbis.c index d54087f..e5fc13e 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -2325,6 +2325,11 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } done: CHECK(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + temp_free(f,part_classdata); + #else + temp_free(f,classifications); + #endif temp_alloc_restore(f,temp_alloc_point); } @@ -2970,6 +2975,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) } } + temp_free(f,buf2); temp_alloc_restore(f,save_point); } From 0e3506d7d187a12413cac1c6fc7f5055e76f7bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Thu, 24 Mar 2016 18:20:39 +0100 Subject: [PATCH 292/522] stb_vorbis: Fix memory leak in start_decoder(). --- stb_vorbis.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index d54087f..dc26094 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3883,7 +3883,6 @@ static int start_decoder(vorb *f) } } } - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); c->lookup_type = 2; } else @@ -3899,11 +3898,11 @@ static int start_decoder(vorb *f) if (c->sequence_p) last = val; } - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); } #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK skip:; #endif + setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); CHECK(f); } From 50479cb07c765229e78420feb126f9fd218d1357 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 26 Mar 2016 15:46:59 -0700 Subject: [PATCH 293/522] stb_image: allow jpegs that are rgb not YCrCb --- stb_image.h | 23 +- tests/stb.dsw | 12 + tools/unicode.c | 749 ++++++++++++++++++++++++++++++++++++++ tools/unicode/unicode.dsp | 88 +++++ 4 files changed, 869 insertions(+), 3 deletions(-) create mode 100644 tools/unicode.c create mode 100644 tools/unicode/unicode.dsp diff --git a/stb_image.h b/stb_image.h index e06f7a1..84b1f9b 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1506,6 +1506,7 @@ typedef struct int succ_high; int succ_low; int eob_run; + int rgb; int scan_n, order[4]; int restart_interval, todo; @@ -2717,11 +2718,17 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + z->rgb = 0; for (i=0; i < s->img_n; ++i) { + static unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); if (z->img_comp[i].id != i+1) // JFIF requires - if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! - return stbi__err("bad component ID","Corrupt JPEG"); + if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files! + // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format) + if (z->img_comp[i].id != rgb[i]) + return stbi__err("bad component ID","Corrupt JPEG"); + ++z->rgb; + } q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); @@ -3383,7 +3390,17 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (n >= 3) { stbi_uc *y = coutput[0]; if (z->s->img_n == 3) { - z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + if (z->rgb == 3) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } } else for (i=0; i < z->s->img_x; ++i) { out[0] = out[1] = out[2] = y[i]; diff --git a/tests/stb.dsw b/tests/stb.dsw index 5e5a120..f73f9b1 100644 --- a/tests/stb.dsw +++ b/tests/stb.dsw @@ -123,6 +123,18 @@ Package=<4> ############################################################################### +Project: "unicode"=..\tools\unicode\unicode.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Project: "vorbseek"=.\vorbseek\vorbseek.dsp - Package Owner=<4> Package=<5> diff --git a/tools/unicode.c b/tools/unicode.c new file mode 100644 index 0000000..8b9d8da --- /dev/null +++ b/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/tools/unicode/unicode.dsp b/tools/unicode/unicode.dsp new file mode 100644 index 0000000..78e6a5b --- /dev/null +++ b/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 From c66b565cb31454533a031df09fe4bef03e344120 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 1 Apr 2016 22:06:19 -0700 Subject: [PATCH 294/522] cro_mipmap --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 209b563..3be8fd2 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -81,6 +81,7 @@ images | [nanoSVG](https://github.com/memononen/nanosvg) images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | C++ | 2 | 2-file jpeg compress, 2-file jpeg decompress images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images +images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings From 86bff62371351e6d17f4cd20a11168d6616a1a09 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 1 Apr 2016 22:15:47 -0700 Subject: [PATCH 295/522] greatest; munit; parg --- docs/other_libs.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 3be8fd2..1cb798a 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -36,6 +36,7 @@ as C/C++, as this is not an obstacle to most users.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* +argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | argv parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression @@ -117,6 +118,8 @@ tests | [catch](https://github.com/philsquared/Catch) tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD |C/C++|**1**| unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing +tests | [greatest](https://github.com/silentbicycle/greatest) | iSC | C |**1**| unit testing +tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++*| 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging From 4ff6723a6d7099b32a8bca2c0fc9438109476b17 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 02:13:20 -0700 Subject: [PATCH 296/522] make resample_test work in VC6 --- stb_truetype.h | 54 ----------------------------------- tests/resample_test.cpp | 62 ++++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 83 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 27ddc05..57a38e6 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -706,18 +706,6 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); // as above, but takes one or more glyph indices for greater efficiency -typedef struct stbtt_kerningentry -{ - int glyph1; // use stbtt_FindGlyphIndex - int glyph2; - int advance; -} stbtt_kerningentry; - -STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); -STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); -// Retrieves a complete list of all of the kerning pairs provided by the font -// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. -// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) ////////////////////////////////////////////////////////////////////////////// // @@ -1490,48 +1478,6 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) -{ - stbtt_uint8 *data = info->data + info->kern; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - return ttUSHORT(data+10); -} - -STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) -{ - stbtt_uint8 *data = info->data + info->kern; - int k, length; - - // we only look at the first table. it must be 'horizontal' and format 0. - if (!info->kern) - return 0; - if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 - return 0; - if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format - return 0; - - length = ttUSHORT(data+10); - if (table_length < length) - length = table_length; - - for (k = 0; k < length; k++) - { - table[k].glyph1 = ttUSHORT(data+18+(k*6)); - table[k].glyph2 = ttUSHORT(data+20+(k*6)); - table[k].advance = ttSHORT(data+22+(k*6)); - } - - return length; -} - STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; diff --git a/tests/resample_test.cpp b/tests/resample_test.cpp index e04962b..2c4a56a 100644 --- a/tests/resample_test.cpp +++ b/tests/resample_test.cpp @@ -514,14 +514,14 @@ void test_subpixel_1() stbir_resize_subpixel(image, 8, 8, 0, output_left, 8, 16, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, 2, 2, 0, 0); stbir_resize_subpixel(image, 8, 8, 0, output_right, 8, 16, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_SRGB, &g_context, 2, 2, 8, 0); - for (int x = 0; x < 8; x++) + {for (int x = 0; x < 8; x++) { for (int y = 0; y < 16; y++) { STBIR_ASSERT(output_data[y * 16 + x] == output_left[y * 8 + x]); STBIR_ASSERT(output_data[y * 16 + x + 8] == output_right[y * 8 + x]); } - } + }} } // test that replicating an image and using a subtile of it produces same results as wraparound @@ -593,11 +593,11 @@ void test_subpixel_3() stbir_resize_subpixel(image, 8, 8, 0, output_data_1, 32, 32, 0, STBIR_TYPE_UINT8, 1, 0, STBIR_ALPHA_CHANNEL_NONE, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_COLORSPACE_LINEAR, NULL, 4, 4, 0, 0); - for (int x = 0; x < 32; x++) + {for (int x = 0; x < 32; x++) { for (int y = 0; y < 32; y++) STBIR_ASSERT(output_data_1[y * 32 + x] == output_data_2[y * 32 + x]); - } + }} } // test that 1:1 resample using s,t=0,0,1,1 with bilinear produces original image @@ -965,19 +965,19 @@ void test_suite(int argc, char **argv) int res = 10; // Downscaling - for (int i = 0; i <= res; i++) + {for (int i = 0; i <= res; i++) { float t = (float)i/res; float scale = 0.5; - float out_scale = 2.0/3; + float out_scale = 2.0f/3; float x_shift = (barbara_width*out_scale - barbara_width*scale) * t; float y_shift = (barbara_height*out_scale - barbara_height*scale) * t; test_subpixel_command(barbara, scale, scale, out_scale, out_scale, x_shift, y_shift); - } + }} // Upscaling - for (int i = 0; i <= res; i++) + {for (int i = 0; i <= res; i++) { float t = (float)i/res; float scale = 2; @@ -986,40 +986,44 @@ void test_suite(int argc, char **argv) float y_shift = (barbara_height*out_scale - barbara_height*scale) * t; test_subpixel_command(barbara, scale, scale, out_scale, out_scale, x_shift, y_shift); - } + }} // Downscaling - for (int i = 0; i <= res; i++) + {for (int i = 0; i <= res; i++) { float t = (float)i/res / 2; test_subpixel_region(barbara, 0.25f, 0.25f, t, t, t+0.5f, t+0.5f); - } + }} // No scaling - for (int i = 0; i <= res; i++) + {for (int i = 0; i <= res; i++) { float t = (float)i/res / 2; test_subpixel_region(barbara, 0.5f, 0.5f, t, t, t+0.5f, t+0.5f); - } + }} // Upscaling - for (int i = 0; i <= res; i++) + {for (int i = 0; i <= res; i++) { float t = (float)i/res / 2; test_subpixel_region(barbara, 1, 1, t, t, t+0.5f, t+0.5f); - } + }} - for (i = 0; i < 10; i++) + {for (i = 0; i < 10; i++) test_subpixel(barbara, 0.5f, 0.5f, (float)i / 10, 1); + } - for (i = 0; i < 10; i++) + {for (i = 0; i < 10; i++) test_subpixel(barbara, 0.5f, 0.5f, 1, (float)i / 10); + } - for (i = 0; i < 10; i++) + {for (i = 0; i < 10; i++) test_subpixel(barbara, 2, 2, (float)i / 10, 1); + } - for (i = 0; i < 10; i++) + {for (i = 0; i < 10; i++) test_subpixel(barbara, 2, 2, 1, (float)i / 10); + } // Channels test test_channels(barbara, 0.5f, 0.5f, 1); @@ -1045,40 +1049,40 @@ void test_suite(int argc, char **argv) resize_image(barbara, 0.5f, 0.5f, STBIR_FILTER_CATMULLROM , STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB, "test-output/barbara-downsample-catmullrom.png"); resize_image(barbara, 0.5f, 0.5f, STBIR_FILTER_MITCHELL , STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB, "test-output/barbara-downsample-mitchell.png"); - for (i = 10; i < 100; i++) + {for (i = 10; i < 100; i++) { char outname[200]; sprintf(outname, "test-output/barbara-width-%d.jpg", i); resize_image(barbara, (float)i / 100, 1, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB, outname); - } + }} - for (i = 110; i < 500; i += 10) + {for (i = 110; i < 500; i += 10) { char outname[200]; sprintf(outname, "test-output/barbara-width-%d.jpg", i); resize_image(barbara, (float)i / 100, 1, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB, outname); - } + }} - for (i = 10; i < 100; i++) + {for (i = 10; i < 100; i++) { char outname[200]; sprintf(outname, "test-output/barbara-height-%d.jpg", i); resize_image(barbara, 1, (float)i / 100, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB, outname); - } + }} - for (i = 110; i < 500; i += 10) + {for (i = 110; i < 500; i += 10) { char outname[200]; sprintf(outname, "test-output/barbara-height-%d.jpg", i); resize_image(barbara, 1, (float)i / 100, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB, outname); - } + }} - for (i = 50; i < 200; i += 10) + {for (i = 50; i < 200; i += 10) { char outname[200]; sprintf(outname, "test-output/barbara-width-height-%d.jpg", i); resize_image(barbara, 100 / (float)i, (float)i / 100, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB, outname); - } + }} test_format(barbara, 0.5, 2.0, STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB); test_format(barbara, 0.5, 2.0, STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR); From 814bb9b5dcda1942d20d96e8d97505fde96b73a0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 02:36:24 -0700 Subject: [PATCH 297/522] remove STBIR__DEBUG_ASSERT because it requires defining/not-defining assert() in a warning-free way on all platforms independent of #include , which is too hard --- stb_image_resize.h | 97 +++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 9177d14..da0a74c 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -383,15 +383,6 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int #define STBIR_ASSERT(x) assert(x) #endif -#ifdef STBIR_DEBUG -#define STBIR__DEBUG_ASSERT STBIR_ASSERT -#else -#define STBIR__DEBUG_ASSERT -#endif - -// If you hit this it means I haven't done it yet. -#define STBIR__UNIMPLEMENTED(x) STBIR_ASSERT(!(x)) - // For memset #include @@ -758,7 +749,7 @@ static float stbir__filter_trapezoid(float x, float scale) { float halfscale = scale / 2; float t = 0.5f + halfscale; - STBIR__DEBUG_ASSERT(scale <= 1); + STBIR_ASSERT(scale <= 1); x = (float)fabs(x); @@ -776,7 +767,7 @@ static float stbir__filter_trapezoid(float x, float scale) static float stbir__support_trapezoid(float scale) { - STBIR__DEBUG_ASSERT(scale <= 1); + STBIR_ASSERT(scale <= 1); return 0.5f + scale / 2; } @@ -990,7 +981,7 @@ static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) return n; // NOTREACHED default: - STBIR__UNIMPLEMENTED("Unimplemented edge type"); + STBIR_ASSERT(!"Unimplemented edge type"); return 0; } } @@ -1039,12 +1030,12 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi float total_filter = 0; float filter_scale; - STBIR__DEBUG_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. contributor->n0 = in_first_pixel; contributor->n1 = in_last_pixel; - STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0); + STBIR_ASSERT(contributor->n1 >= contributor->n0); for (i = 0; i <= in_last_pixel - in_first_pixel; i++) { @@ -1062,10 +1053,10 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi total_filter += coefficient_group[i]; } - STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); - STBIR__DEBUG_ASSERT(total_filter > 0.9); - STBIR__DEBUG_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. // Make sure the sum of all coefficients is 1. filter_scale = 1 / total_filter; @@ -1087,12 +1078,12 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st { int i; - STBIR__DEBUG_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. contributor->n0 = out_first_pixel; contributor->n1 = out_last_pixel; - STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0); + STBIR_ASSERT(contributor->n1 >= contributor->n0); for (i = 0; i <= out_last_pixel - out_first_pixel; i++) { @@ -1101,7 +1092,7 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; } - STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); for (i = out_last_pixel - out_first_pixel; i >= 0; i--) { @@ -1136,8 +1127,8 @@ static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, st break; } - STBIR__DEBUG_ASSERT(total > 0.9f); - STBIR__DEBUG_ASSERT(total < 1.1f); + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); scale = 1 / total; @@ -1364,7 +1355,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) break; default: - STBIR__UNIMPLEMENTED("Unknown type/colorspace/channels combination."); + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); break; } @@ -1425,7 +1416,7 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) else { ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width; - STBIR__DEBUG_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); } ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); @@ -1457,11 +1448,11 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, int coefficient_group = coefficient_width * x; int coefficient_counter = 0; - STBIR__DEBUG_ASSERT(n1 >= n0); - STBIR__DEBUG_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); - STBIR__DEBUG_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); - STBIR__DEBUG_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); - STBIR__DEBUG_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); switch (channels) { case 1: @@ -1469,7 +1460,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 1; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; } break; @@ -1478,7 +1469,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 2; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; } @@ -1488,7 +1479,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 3; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1499,7 +1490,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, { int in_pixel_index = k * 4; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1512,7 +1503,7 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, int in_pixel_index = k * channels; float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; int c; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); for (c = 0; c < channels; c++) output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; } @@ -1535,7 +1526,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; int max_x = input_w + filter_pixel_margin * 2; - STBIR__DEBUG_ASSERT(!stbir__use_width_upsampling(stbir_info)); + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); switch (channels) { case 1: @@ -1553,7 +1544,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 1; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; } } @@ -1574,7 +1565,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 2; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; } @@ -1596,7 +1587,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 3; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1619,7 +1610,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n { int out_pixel_index = k * 4; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; @@ -1644,7 +1635,7 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n int c; int out_pixel_index = k * channels; float coefficient = horizontal_coefficients[coefficient_group + k - n0]; - STBIR__DEBUG_ASSERT(coefficient != 0); + STBIR_ASSERT(coefficient != 0); for (c = 0; c < channels; c++) output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; } @@ -1856,7 +1847,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void break; default: - STBIR__UNIMPLEMENTED("Unknown type/colorspace/channels combination."); + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); break; } } @@ -1893,7 +1884,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in output_row_start = n * stbir_info->output_stride_bytes; - STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); memset(encode_buffer, 0, output_w * sizeof(float) * channels); @@ -2003,7 +1994,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, n0 = vertical_contributors[contributor].n0; n1 = vertical_contributors[contributor].n1; - STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); for (k = n0; k <= n1; k++) { @@ -2068,7 +2059,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) float scale_ratio = stbir_info->vertical_scale; float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; - STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); for (y = 0; y < stbir_info->output_h; y++) { @@ -2077,7 +2068,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); - STBIR__DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width); if (stbir_info->ring_buffer_begin_index >= 0) { @@ -2169,7 +2160,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) int pixel_margin = stbir_info->vertical_filter_pixel_margin; int max_y = stbir_info->input_h + pixel_margin; - STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info)); + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); for (y = -pixel_margin; y < max_y; y++) { @@ -2178,7 +2169,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); - STBIR__DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width); if (out_last_scanline < 0 || out_first_scanline >= output_h) continue; @@ -2380,7 +2371,7 @@ static int stbir__resize_allocated(stbir__info *info, info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); - STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); } else { @@ -2388,7 +2379,7 @@ static int stbir__resize_allocated(stbir__info *info, info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); info->encode_buffer = NULL; - STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); } #undef STBIR__NEXT_MEMPTR @@ -2409,10 +2400,10 @@ static int stbir__resize_allocated(stbir__info *info, STBIR_PROGRESS_REPORT(1); #ifdef STBIR_DEBUG_OVERWRITE_TEST - STBIR__DEBUG_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); - STBIR__DEBUG_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); - STBIR__DEBUG_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); - STBIR__DEBUG_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); #endif return 1; From a013c036f3edc80c67ddb9556dd1d9a986cd6af7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 02:54:25 -0700 Subject: [PATCH 298/522] initialize bmp mr/mg/mb/ma properly --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 893a876..1abe6f4 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4724,6 +4724,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) stbi__get16le(s); // discard reserved info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { @@ -4752,7 +4753,6 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) stbi__get32le(s); } if (info->bpp == 16 || info->bpp == 32) { - info->mr = info->mg = info->mb = 0; if (compress == 0) { if (info->bpp == 32) { info->mr = 0xffu << 16; From b7603b0ca6245ea6ff61b8bfb713dda0c5261f88 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:34:51 -0700 Subject: [PATCH 299/522] dr_flac --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 1cb798a..d50fe16 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -38,6 +38,7 @@ category | library AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | argv parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder +audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/archive/p/fastlz/source/default/source) | MIT |C/C++| 2 | fast but larger LZ compression From aeba55604a52690921ea3e94543d017906c6aa21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Thu, 24 Mar 2016 18:20:39 +0100 Subject: [PATCH 300/522] stb_vorbis: Fix memory leak in start_decoder(). --- stb_vorbis.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 4cd02de..6baf9ec 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3810,7 +3810,6 @@ static int start_decoder(vorb *f) } } } - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); c->lookup_type = 2; } else @@ -3826,11 +3825,11 @@ static int start_decoder(vorb *f) if (c->sequence_p) last = val; } - setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); } #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK skip:; #endif + setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); CHECK(f); } From a8876b884d6a916497e534d0b241734a79f46db9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:40:42 -0700 Subject: [PATCH 301/522] fix _WIN32 if STB_THREADS --- stb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb.h b/stb.h index 11350ba..89aac37 100644 --- a/stb.h +++ b/stb.h @@ -11205,7 +11205,7 @@ int stb_arith_decode_byte(stb_arith *a) // Threads // -#ifndef WIN32 +#ifndef _WIN32 #ifdef STB_THREADS #error "threads not implemented except for Windows" #endif From 591c7f8cb348a3915a4afa64e102e7b225119cd6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:40:55 -0700 Subject: [PATCH 302/522] remove white matting when loading transparent PSD --- stb_image.h | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 80a4231..af663cf 100644 --- a/stb_image.h +++ b/stb_image.h @@ -201,10 +201,11 @@ Janez Zemva John Bartholomew Michal Cichon svdijk@github Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github - Aruelien Pocheville Thibault Reuille Cass Everitt + Aruelien Pocheville Thibault Reuille Cass Everitt Ryamond Barbiero Paul Du Bois Engin Manap + Michaelangel007@github Oriol Ferrer Mesia Blazej Dariusz Roszkowski - Michaelangel007@github + Oriol Ferrer Mesia LICENSE @@ -5453,6 +5454,21 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int } } + if (channelCount >= 3) { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + // remove weird white matte from PSD + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + if (req_comp && req_comp != 4) { out = stbi__convert_format(out, 4, req_comp, w, h); if (out == NULL) return out; // stbi__convert_format frees input on failure From 75c5908f951513bdc619fd7c9cb3b96283d4f397 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:41:26 -0700 Subject: [PATCH 303/522] fix includes for linux alloca --- stb_vorbis.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stb_vorbis.c b/stb_vorbis.c index 6baf9ec..0642c11 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -552,6 +552,9 @@ enum STBVorbisError #include #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) #include +#if defined(__linux__) || defined(__linux) +#include +#endif #endif #else // STB_VORBIS_NO_CRT #define NULL 0 From 201af99d9fd26bae939ad7f2395920476f78d7f1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:49:46 -0700 Subject: [PATCH 304/522] return correct # of channels for PNG --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index af663cf..4f2f4b7 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4606,7 +4606,7 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req } *x = p->s->img_x; *y = p->s->img_y; - if (n) *n = p->s->img_out_n; + if (n) *n = p->s->img_n; } STBI_FREE(p->out); p->out = NULL; STBI_FREE(p->expanded); p->expanded = NULL; From 5990ff8a476ad890a42649179b346355daa0133f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:51:19 -0700 Subject: [PATCH 305/522] remove duplicate typedef of stbtt_fontinfo --- stb_truetype.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index c5201f8..b24aa19 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -634,7 +634,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // The following structure is defined publically so you can declare one on // the stack or as a global or etc, but you should treat it as opaque. -typedef struct stbtt_fontinfo +struct stbtt_fontinfo { void * userdata; unsigned char * data; // pointer to .ttf file @@ -645,7 +645,7 @@ typedef struct stbtt_fontinfo int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph -} stbtt_fontinfo; +}; STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); // Given an offset into the file that defines a font, this function builds From 538b96d6e2fe72ce1627dbcb2df0f891d03732ef Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:52:47 -0700 Subject: [PATCH 306/522] remove claims of supporting C++ in stretchy_buffer --- stretchy_buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stretchy_buffer.h b/stretchy_buffer.h index b9a493c..9b47a67 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -2,7 +2,7 @@ // a vector<>-like dynamic array for C // // version history: -// 1.02 - compiles as C++, but untested +// 1.02 - tweaks to syntax for no good reason // 1.01 - added a "common uses" documentation section // 1.0 - fixed bug in the version I posted prematurely // 0.9 - rewrite to try to avoid strict-aliasing optimization From 56e8fd063ce8105ba05884a540763068b744bf2f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:55:03 -0700 Subject: [PATCH 307/522] don't leak vertex data if text is scaled to 0 --- stb_truetype.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_truetype.h b/stb_truetype.h index b24aa19..d59c37d 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -2435,7 +2435,10 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info if (scale_x == 0) scale_x = scale_y; if (scale_y == 0) { - if (scale_x == 0) return NULL; + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } scale_y = scale_x; } From 92bd7a49a8b899c56db45976afb338bc4bd2c65a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 03:57:17 -0700 Subject: [PATCH 308/522] emscripten needs explicit alloca as well --- stb_vorbis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 0642c11..b173a20 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -552,7 +552,7 @@ enum STBVorbisError #include #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) #include -#if defined(__linux__) || defined(__linux) +#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) #include #endif #endif From 7a694bdccafb2995936a81dd1ab27065da514019 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 04:01:59 -0700 Subject: [PATCH 309/522] re-enable SSE2 code on x64 except with gcc --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 4f2f4b7..cb24fe5 100644 --- a/stb_image.h +++ b/stb_image.h @@ -673,7 +673,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_NO_SIMD #endif -#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET) +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) #define STBI_SSE2 #include From b03133000a7f7d49aa3ce57bb5fa1975dd41db21 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 04:20:36 -0700 Subject: [PATCH 310/522] avoid dropping final frame of audio data due to wrong test --- release_notes.md | 28 ++++++++++++++++++++++++++++ stb_vorbis.c | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 release_notes.md diff --git a/release_notes.md b/release_notes.md new file mode 100644 index 0000000..b6e50f4 --- /dev/null +++ b/release_notes.md @@ -0,0 +1,28 @@ +---- + +2016-04-02: + +- other_libs: cro_mipmap, greatest, munit, parg, dr_flac +- stb_image: support images coded as RGB +- stb_voxel_render: fix type of glModelview matrix (Stephen Olsen) +- stb_textedit: better support for keying while holding mouse drag button (ocornut) +- stb_image: bmp could return wrong channel count (snagar@github) +- stb_image_resize: fix handling of subpixel regions +- stb_image_resize: avoid warnings on asserts (Wu Shuang) +- stb_truetype: allow fabs() to be supplied by user (Simon Glass) +- stb_image: read 16-bit PNGs as 8-bit (socks-the-fox) +- stb_leakcheck: typo in comment (Lukas Meller) +- stb_vorbis: warnings (Thiago Goulart) +- stb_image: allocate large structures on stack for embedded (Thatcher Ulrich) +- stb_image_write: allocate large structures on stack for embedded (Thatcher Ulrich) +- stb_image: fix harmless typo in name (Matthew Gregan) +- stb_vorbis: fix multiple memory leaks of setup-memory (manxorist@github) +- stb_image: remove white matting for transparent PSD (stb, Oriol Ferrer Mesia) +- stb.h: fix _WIN32 when defining STB_THREADS +- stb_image: fix reported channel count in PNG when req_comp is non-zero +- stb_truetype: duplicate typedef +- stb_truetype: don't leak memory if fontsize=0 +- stb_image: re-enable SSE2 in x64 (except in gcc) + + + diff --git a/stb_vorbis.c b/stb_vorbis.c index b173a20..7676c60 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3508,7 +3508,7 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page) } // either this continues, or it ends it... if (end_page) - if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream); + if (s < f->segment_count) return error(f, VORBIS_invalid_stream); if (s == f->segment_count) s = -1; // set 'crosses page' flag if (p > f->stream_end) return error(f, VORBIS_need_more_data); From 6e4154737c51c1298e35cc6fc387dd365cc32ac9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 04:51:26 -0700 Subject: [PATCH 311/522] update version numbers, documentation, and contributors --- README.md | 18 +++++++++--------- release_notes.md | 30 ++++++++++++++---------------- stb.h | 5 +++-- stb_image.h | 23 ++++++++++++++--------- stb_image_resize.h | 3 ++- stb_image_write.h | 5 ++++- stb_textedit.h | 3 ++- stb_truetype.h | 13 +++++++++---- stb_vorbis.c | 10 +++++++--- stb_voxel_render.h | 4 +++- 10 files changed, 67 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index a5fdd4a..87b00fe 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,15 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**stb_vorbis.c** | 1.07 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.10 | graphics | 6614 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.09 | graphics | 3249 | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 1.01 | graphics | 1044 | image writing to disk: PNG, TGA, BMP -**stb_image_resize.h** | 0.90 | graphics | 2586 | resize images larger/smaller with good quality +**stb_vorbis.c** | 1.08 | audio | 5395 | decode ogg vorbis files from file/memory to float/16-bit signed output +**stb_image.h** | 2.11 | graphics | 6753 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_truetype.h** | 1.10 | graphics | 3262 | parse, decode, and rasterize characters from truetype fonts +**stb_image_write.h** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP +**stb_image_resize.h** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**stb_textedit.h** | 1.7 | user interface | 1301 | guts of a text editor for games etc implementing them from scratch -**stb_voxel_render.h** | 0.83 | 3D graphics | 3750 | Minecraft-esque voxel rendering "engine" with many more features +**stb_textedit.h** | 1.8 | user interface | 1304 | guts of a text editor for games etc implementing them from scratch +**stb_voxel_render.h** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features **stb_dxt.h** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **stb_perlin.h** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) **stb_easy_font.h** | 0.7 | 3D graphics | 258 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc @@ -23,11 +23,11 @@ library | lastest version | category | LoC | description **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**stb.h** | 2.26 | misc | 14184 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**stb.h** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46718 +Total lines of C code: 46805 FAQ diff --git a/release_notes.md b/release_notes.md index b6e50f4..9a266ce 100644 --- a/release_notes.md +++ b/release_notes.md @@ -3,26 +3,24 @@ 2016-04-02: - other_libs: cro_mipmap, greatest, munit, parg, dr_flac +- stb_image_write: allocate large structures on stack for embedded (Thatcher Ulrich) +- stb_image: allocate large structures on stack for embedded (Thatcher Ulrich) +- stb_image: remove white matting for transparent PSD (stb, Oriol Ferrer Mesia) +- stb_image: fix reported channel count in PNG when req_comp is non-zero +- stb_image: re-enable SSE2 in x64 (except in gcc) +- stb_image: fix harmless typo in name (Matthew Gregan) - stb_image: support images coded as RGB -- stb_voxel_render: fix type of glModelview matrix (Stephen Olsen) -- stb_textedit: better support for keying while holding mouse drag button (ocornut) - stb_image: bmp could return wrong channel count (snagar@github) +- stb_image: read 16-bit PNGs as 8-bit (socks-the-fox) - stb_image_resize: fix handling of subpixel regions - stb_image_resize: avoid warnings on asserts (Wu Shuang) - stb_truetype: allow fabs() to be supplied by user (Simon Glass) -- stb_image: read 16-bit PNGs as 8-bit (socks-the-fox) -- stb_leakcheck: typo in comment (Lukas Meller) -- stb_vorbis: warnings (Thiago Goulart) -- stb_image: allocate large structures on stack for embedded (Thatcher Ulrich) -- stb_image_write: allocate large structures on stack for embedded (Thatcher Ulrich) -- stb_image: fix harmless typo in name (Matthew Gregan) -- stb_vorbis: fix multiple memory leaks of setup-memory (manxorist@github) -- stb_image: remove white matting for transparent PSD (stb, Oriol Ferrer Mesia) -- stb.h: fix _WIN32 when defining STB_THREADS -- stb_image: fix reported channel count in PNG when req_comp is non-zero - stb_truetype: duplicate typedef - stb_truetype: don't leak memory if fontsize=0 -- stb_image: re-enable SSE2 in x64 (except in gcc) - - - +- stb_vorbis: warnings (Thiago Goulart) +- stb_vorbis: fix multiple memory leaks of setup-memory (manxorist@github) +- stb_vorbis: avoid dropping final frame of audio data +- stb_textedit: better support for keying while holding mouse drag button (ocornut) +- stb_voxel_render: fix type of glModelview matrix (Stephen Olsen) +- stb_leakcheck: typo in comment (Lukas Meller) +- stb.h: fix _WIN32 when defining STB_THREADS diff --git a/stb.h b/stb.h index 89aac37..b985b13 100644 --- a/stb.h +++ b/stb.h @@ -1,4 +1,4 @@ -/* stb.h - v2.26 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h +/* stb.h - v2.27 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h no warranty is offered or implied; use this code at your own risk This is a single header file with a bunch of useful utilities @@ -25,7 +25,8 @@ Version History - 2.26 various warning & buffixes + 2.27 test _WIN32 not WIN32 in STB_THREADS + 2.26 various warning & bugfixes 2.25 various warning & bugfixes 2.24 various warning & bugfixes 2.23 fix 2.22 diff --git a/stb_image.h b/stb_image.h index cb24fe5..6e1dbec 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.10 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.11 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -146,6 +146,10 @@ Latest revision history: + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA @@ -167,10 +171,6 @@ STBI_MALLOC,STBI_REALLOC,STBI_FREE STBI_NO_*, STBI_ONLY_* GIF bugfix - 1.48 (2014-12-14) fix incorrectly-named assert() - 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted) - optimize PNG - fix bug in interlaced PNG with user-specified channel count See end of file for full revision history. @@ -201,11 +201,10 @@ Janez Zemva John Bartholomew Michal Cichon svdijk@github Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github - Aruelien Pocheville Thibault Reuille Cass Everitt - Ryamond Barbiero Paul Du Bois Engin Manap - Michaelangel007@github Oriol Ferrer Mesia + Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan + Ryamond Barbiero Paul Du Bois Engin Manap snagar@github + Michaelangel007@github Oriol Ferrer Mesia socks-the-fox Blazej Dariusz Roszkowski - Oriol Ferrer Mesia LICENSE @@ -6593,6 +6592,12 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED 2.09 (2016-01-16) allow comments in PNM files 16-bit-per-pixel TGA (not bit-per-component) diff --git a/stb_image_resize.h b/stb_image_resize.h index da0a74c..4cabe54 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1,4 +1,4 @@ -/* stb_image_resize - v0.90 - public domain image resizing +/* stb_image_resize - v0.91 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb @@ -156,6 +156,7 @@ Sean Barrett: API design, optimizations REVISIONS + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions 0.90 (2014-09-17) first released version LICENSE diff --git a/stb_image_write.h b/stb_image_write.h index e9f952a..4319c0d 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.01 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -102,6 +102,7 @@ CREDITS: Sergio Gonzalez Jonas Karlsson Filip Wasil + Thatcher Ulrich LICENSE @@ -1016,6 +1017,8 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.02 (2016-04-02) + avoid allocating large structures on the stack 1.01 (2016-01-16) STBIW_REALLOC_SIZED: support allocators with no realloc support avoid race-condition in crc initialization diff --git a/stb_textedit.h b/stb_textedit.h index 7de387c..29af484 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// stb_textedit.h - v1.7 - public domain - Sean Barrett +// stb_textedit.h - v1.8 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -31,6 +31,7 @@ // // VERSION HISTORY // +// 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.7 (2015-09-13) change y range handling in case baseline is non-0 // 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove // 1.5 (2014-09-10) add support for secondary keys for OS X diff --git a/stb_truetype.h b/stb_truetype.h index d59c37d..e646a90 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.09 - public domain +// stb_truetype.h - v1.10 - public domain // authored from 2009-2015 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -21,6 +21,10 @@ // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering // +// Misc other: +// Ryan Gordon +// Simon Glass +// // Bug/warning reports/fixes: // "Zer" on mollyrocket (with fix) // Cass Everitt @@ -45,11 +49,9 @@ // Thomas Fields // Derek Vinyard // -// Misc other: -// Ryan Gordon -// // VERSION HISTORY // +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; @@ -3213,6 +3215,9 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // FULL VERSION HISTORY // +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; diff --git a/stb_vorbis.c b/stb_vorbis.c index 7676c60..ac8fc19 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.07 - public domain +// Ogg Vorbis audio decoder - v1.08 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -31,11 +31,13 @@ // Terje Mathisen Niklas Frykholm Andy Hill // Casey Muratori John Bolton Gargaj // Laurent Gomila Marc LeBlanc Ronny Chevalier -// Bernhard Wodo Evan Balster "alxprd"@github +// Bernhard Wodo Evan Balster alxprd@github // Tom Beaumont Ingo Leitgeb Nicolas Guillemot -// Phillip Bennefall Rohit +// Phillip Bennefall Rohit Thiago Goulart +// manxorist@github saga musix // // Partial history: +// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame // 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const // 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) // some crash fixes when out of memory or with corrupt files @@ -5340,6 +5342,8 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; + avoid discarding last frame of audio data 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API some more crash fixes when out of memory or with corrupt files 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index bb227fd..c49aa40 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -1,4 +1,4 @@ -// stb_voxel_render.h - v0.83 - Sean Barrett, 2015 - public domain +// stb_voxel_render.h - v0.84 - Sean Barrett, 2015 - public domain // // This library helps render large-scale "voxel" worlds for games, // in this case, one with blocks that can have textures and that @@ -187,9 +187,11 @@ // Sean Barrett github:r-leyh Jesus Fernandez // Miguel Lechon github:Arbeiterunfallversicherungsgesetz // Thomas Frase James Hofmann +// Stephen Olsen // // VERSION HISTORY // +// 0.84 (2016-04-02) fix GLSL syntax error on glModelView path // 0.83 (2015-09-13) remove non-constant struct initializers to support more compilers // 0.82 (2015-08-01) added input.packed_compact to store rot, vheight & texlerp efficiently // fix broken tex_overlay2 From 136455df6db9d5868411d3136ae8b70fe11ed081 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 04:55:44 -0700 Subject: [PATCH 312/522] clarify --- release_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release_notes.md b/release_notes.md index 9a266ce..6712e9d 100644 --- a/release_notes.md +++ b/release_notes.md @@ -9,7 +9,7 @@ - stb_image: fix reported channel count in PNG when req_comp is non-zero - stb_image: re-enable SSE2 in x64 (except in gcc) - stb_image: fix harmless typo in name (Matthew Gregan) -- stb_image: support images coded as RGB +- stb_image: support JPEG images coded as RGB - stb_image: bmp could return wrong channel count (snagar@github) - stb_image: read 16-bit PNGs as 8-bit (socks-the-fox) - stb_image_resize: fix handling of subpixel regions From fdca443892d0ce3c8680e6f38f196c61e95c7de3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 07:29:34 -0700 Subject: [PATCH 313/522] fix crash in 2.11 --- stb_image.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 6e1dbec..a3c1129 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.11 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -146,6 +146,7 @@ Latest revision history: + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; allocate large structures on the stack; @@ -5453,7 +5454,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int } } - if (channelCount >= 3) { + if (channelCount >= 4) { for (i=0; i < w*h; ++i) { unsigned char *pixel = out + 4*i; if (pixel[3] != 0 && pixel[3] != 255) { @@ -6592,6 +6593,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) allocate large structures on the stack remove white matting for transparent PSD fix reported channel count for PNG & BMP From a1a918a4877c6831e48ee69f8026f2f810257c24 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 13:45:32 -0700 Subject: [PATCH 314/522] fix unused variable warning --- stb_truetype.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index e646a90..d360d60 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.10 - public domain +// stb_truetype.h - v1.11 - public domain // authored from 2009-2015 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -51,6 +51,7 @@ // // VERSION HISTORY // +// 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges @@ -949,6 +950,12 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define STBTT_RASTERIZER_VERSION 2 #endif +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file @@ -2078,6 +2085,8 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int y,j=0, i; float scanline_data[129], *scanline, *scanline2; + STBTT__NOTUSED(vsubsample); + if (result->w > 64) scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); else @@ -2596,11 +2605,6 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int // #ifndef STB_RECT_PACK_VERSION -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif typedef int stbrp_coord; @@ -3215,6 +3219,7 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // FULL VERSION HISTORY // +// 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) allow user-defined fabs() replacement // fix memory leak if fontsize=0.0 // fix warning from duplicate typedef From 62d773db5db889e5a5000627625173ec9affd7a6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 2 Apr 2016 13:46:11 -0700 Subject: [PATCH 315/522] updat versions --- README.md | 6 +++--- tools/README.footer.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 87b00fe..54a13b4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **stb_vorbis.c** | 1.08 | audio | 5395 | decode ogg vorbis files from file/memory to float/16-bit signed output **stb_image.h** | 2.11 | graphics | 6753 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.10 | graphics | 3262 | parse, decode, and rasterize characters from truetype fonts +**stb_truetype.h** | 1.11 | graphics | 3267 | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality @@ -27,7 +27,7 @@ library | lastest version | category | LoC | description **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46805 +Total lines of C code: 46810 FAQ @@ -99,7 +99,7 @@ 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.c? +#### 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 diff --git a/tools/README.footer.md b/tools/README.footer.md index e910267..b9a52bf 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -68,7 +68,7 @@ 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.c? +#### 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 From 75ce29fe0b1d17c05b56a447a78831a9cf585f2e Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 2 Apr 2016 23:55:01 +0200 Subject: [PATCH 316/522] stb_textedit: Add support for custom move word left/right handlers --- stb_textedit.h | 61 +++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 29af484..4634dcf 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -148,15 +148,17 @@ // STB_TEXTEDIT_K_REDO keyboard input to perform redo // // Optional: -// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode -// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), -// required for WORDLEFT/WORDRIGHT -// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT -// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT -// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line -// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line -// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text -// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text +// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode +// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), +// required for default WORDLEFT/WORDRIGHT handlers +// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to +// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to +// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT +// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT +// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line +// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line +// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text +// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text // // Todo: // STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page @@ -615,9 +617,9 @@ static int is_word_boundary( STB_TEXTEDIT_STRING *_str, int _idx ) return _idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str,_idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str, _idx) ) ) : 1; } -static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, STB_TexteditState *_state ) +#ifndef STB_TEXTEDIT_MOVEWORDLEFT +static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, int c ) { - int c = _state->cursor - 1; while( c >= 0 && !is_word_boundary( _str, c ) ) --c; @@ -626,11 +628,13 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, STB_Te return c; } +#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous +#endif -static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, STB_TexteditState *_state ) +#ifndef STB_TEXTEDIT_MOVEWORDRIGHT +static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, int c ) { const int len = STB_TEXTEDIT_STRINGLEN(_str); - int c = _state->cursor+1; while( c < len && !is_word_boundary( _str, c ) ) ++c; @@ -639,6 +643,9 @@ static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, STB_Texted return c; } +#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next +#endif + #endif // update selection and cursor to match each other @@ -760,21 +767,12 @@ retry: state->has_preferred_x = 0; break; -#ifdef STB_TEXTEDIT_IS_SPACE +#ifdef STB_TEXTEDIT_MOVEWORDLEFT case STB_TEXTEDIT_K_WORDLEFT: if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); else { - state->cursor = stb_textedit_move_to_word_previous(str, state); - stb_textedit_clamp( str, state ); - } - break; - - case STB_TEXTEDIT_K_WORDRIGHT: - if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_last(str, state); - else { - state->cursor = stb_textedit_move_to_word_next(str, state); + state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1); stb_textedit_clamp( str, state ); } break; @@ -783,17 +781,28 @@ retry: if( !STB_TEXT_HAS_SELECTION( state ) ) stb_textedit_prep_selection_at_cursor(state); - state->cursor = stb_textedit_move_to_word_previous(str, state); + state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1); state->select_end = state->cursor; stb_textedit_clamp( str, state ); break; +#endif + +#ifdef STB_TEXTEDIT_MOVEWORDRIGHT + case STB_TEXTEDIT_K_WORDRIGHT: + if (STB_TEXT_HAS_SELECTION(state)) + stb_textedit_move_to_last(str, state); + else { + state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1); + stb_textedit_clamp( str, state ); + } + break; case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: if( !STB_TEXT_HAS_SELECTION( state ) ) stb_textedit_prep_selection_at_cursor(state); - state->cursor = stb_textedit_move_to_word_next(str, state); + state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1); state->select_end = state->cursor; stb_textedit_clamp( str, state ); From 4c519106a7c3862524100f907736c1c74412725d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 4 Apr 2016 18:39:30 -0700 Subject: [PATCH 317/522] back out previous change to stb_vorbis (truncation of last frame in corrupt file) --- README.md | 6 +++--- stb_vorbis.c | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 54a13b4..f813a5b 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**stb_vorbis.c** | 1.08 | audio | 5395 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.11 | graphics | 6753 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_vorbis.c** | 1.09 | audio | 5397 | decode ogg vorbis files from file/memory to float/16-bit signed output +**stb_image.h** | 2.12 | graphics | 6755 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **stb_truetype.h** | 1.11 | graphics | 3267 | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality @@ -27,7 +27,7 @@ library | lastest version | category | LoC | description **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 18 -Total lines of C code: 46810 +Total lines of C code: 46814 FAQ diff --git a/stb_vorbis.c b/stb_vorbis.c index ac8fc19..19459eb 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.08 - public domain +// Ogg Vorbis audio decoder - v1.09 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -37,6 +37,7 @@ // manxorist@github saga musix // // Partial history: +// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version // 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame // 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const // 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) @@ -3510,7 +3511,7 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page) } // either this continues, or it ends it... if (end_page) - if (s < f->segment_count) return error(f, VORBIS_invalid_stream); + if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream); if (s == f->segment_count) s = -1; // set 'crosses page' flag if (p > f->stream_end) return error(f, VORBIS_need_more_data); @@ -5342,6 +5343,7 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; avoid discarding last frame of audio data 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API From 133a5656246de5a6ab202d5317c02a1d27fc3e37 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 14 Apr 2016 07:30:23 -0700 Subject: [PATCH 318/522] yocto stuff --- docs/other_libs.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index d50fe16..27c5130 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -41,7 +41,7 @@ audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/ audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression -compression | [fastlz](https://code.google.com/archive/p/fastlz/source/default/source) | MIT |C/C++| 2 | fast but larger LZ compression +compression | [fastlz](https://code.google.com/archive/p/fastlz/source/default/source) | MIT |C/C++| 2 | fast but larger LZ compression compression | [pithy](https://github.com/johnezang/pithy) | BSD |C/C++| 2 | fast but larger LZ compression crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | C | 2 | high-quality tiny cryptography library data structures|[klib](http://attractivechaos.github.io/klib/) | MIT |C/C++| 2 | many 2-file libs: hash, sort, b-tree, etc @@ -56,6 +56,7 @@ files & filenames | [TinyDir](https://github.com/cxong/tinydir) geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | C++ |**1**| wavefront OBJ file loader +geometry file | [yocto_obj.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| wavefront OBJ file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |C/C++|**1**| find voronoi regions on lattice w/ integer inputs geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |C/C++|**1**| sobol & stratified sampling sequences geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT |C/C++|**1**| compute signed-distance field from antialiased image @@ -67,6 +68,9 @@ geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | C++ | 2 | line & polygon clipping & offsetting geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | C++ | 2 | polygon triangulation, partitioning geometry math | [Voxelizer](https://github.com/karimnaaji/voxelizer) | MIT |C/C++|**1**| convert triangle mesh to voxel triangle mesh +geometry math | [yocto_bvh.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| ray-casting of bounding-volume hierarchy +geometry math | [yocto_shape.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| shape generation, tesselation, normals, etc. +geometry math | [yocto_trace.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| physically-based unidirectional path tracer w/ MIS for direct lights graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator @@ -76,7 +80,7 @@ hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** images | [jo_gif.cpp](http://www.jonolick.com/home/gif-writer) | **public domain** | C++ |**1**| animated GIF writer (CPP file can also be used as H file) images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder -images | [miniexr](https://github.com/aras-p/miniexr) | **public domain** | C++ | 2 | OpenEXR writer, needs header file +images | [miniexr](https://github.com/aras-p/miniexr) | **public domain** | C++ | 2 | OpenEXR writer, needs header file images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |C/C++|**1**| EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer @@ -87,8 +91,8 @@ images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings -math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math -math | [PoissonGenerator.h](https://github.com/corporateshark/poisson-disk-generator) | MIT | C++ |**1**| Poisson disk points generator (disk or rect) +math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math +math | [PoissonGenerator.h](https://github.com/corporateshark/poisson-disk-generator) | MIT | C++ |**1**| Poisson disk points generator (disk or rect) multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby From 1c5a92440d7850a551a53d19c5183c982a4b1230 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 15 Apr 2016 19:22:22 -0700 Subject: [PATCH 319/522] stb_connected_components added --- README.md | 5 +- stb_connected_components.h | 653 +++++++++++++++++++++++++++++++++++++ tools/README.list | 1 + 3 files changed, 657 insertions(+), 2 deletions(-) create mode 100644 stb_connected_components.h diff --git a/README.md b/README.md index f813a5b..05c9d25 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,12 @@ library | lastest version | category | LoC | description **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" +**stb_connected_comp...** | 0.90 | misc | 653 | incrementally compute reachability on grids **stb.h** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking -Total libraries: 18 -Total lines of C code: 46814 +Total libraries: 19 +Total lines of C code: 47467 FAQ diff --git a/stb_connected_components.h b/stb_connected_components.h new file mode 100644 index 0000000..7b91d42 --- /dev/null +++ b/stb_connected_components.h @@ -0,0 +1,653 @@ +// stb_connected_components - v0.90 - public domain connected components on grids +// http://github.com/nothings/stb +// +// Finds connected components on 2D grids for testing reachability between +// two points, with fast updates when changing reachability (e.g. on one machine +// it was typically 0.2ms w/ 1024x1024 grid). Each grid square must be "open" or +// "closed" (traversable or untraversable), and grid squares are only connected +// to their orthogonal neighbors, not diagonally. +// +// In one source file, create the implementation by doing something like this: +// +// #define STBCC_GRID_COUNT_X_LOG2 10 +// #define STBCC_GRID_COUNT_Y_LOG2 10 +// #define STB_CONNECTED_COMPONENTS_IMPLEMENTATION +// #include "stb_connected_components.h" +// +// The above creates an implementation that can run on maps up to 1024x1024. +// Map sizes must be a multiple of 32 on each axis. +// +// LICENSE +// +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. +// + +#ifndef INCLUDE_STB_CONNECTED_COMPONENTS_H +#define INCLUDE_STB_CONNECTED_COMPONENTS_H + +#include +#include + +typedef struct st_stbcc_grid stbcc_grid; + +////////////////////////////////////////////////////////////////////////////////////////// +// +// initialization +// + +// you allocate the grid data structure to this size (note that it will be very big!!!) +extern size_t stbcc_grid_sizeof(void); + +// initialize the grid, value of map[] is 0 = traversable, non-0 is solid +extern void stbcc_init_grid(stbcc_grid *g, unsigned char *map, int w, int h); + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// main functionality +// + +// update a grid square state, 0 = traversable, non-0 is solid +// i can add a batch-update if it's needed +extern void stbcc_update_grid(stbcc_grid *g, int x, int y, int solid); + +// query if two grid squares are reachable from each other +extern int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x2, int y2); + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// bonus functions +// + +// query the grid data structure for whether a given square is open or not +extern int stbcc_query_grid_open(stbcc_grid *g, int x, int y); + +// get a unique id for the connected component this is in; it's not necessarily +// small, you'll need a hash table or something to remap it (or just use +extern unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y); + +#endif // INCLUDE_STB_CONNECTED_COMPONENTS_H + +#ifdef STB_CONNECTED_COMPONENTS_IMPLEMENTATION + +#if !defined(STBCC_GRID_COUNT_X_LOG2) || !defined(STBCC_GRID_COUNT_Y_LOG2) + #error "You must define STBCC_GRID_COUNT_X_LOG2 and STBCC_GRID_COUNT_Y_LOG2 to define the max grid supported." +#endif + +#define STBCC__GRID_COUNT_X (1 << STBCC_GRID_COUNT_X_LOG2) +#define STBCC__GRID_COUNT_Y (1 << STBCC_GRID_COUNT_Y_LOG2) + +#define STBCC__MAP_STRIDE (1 << (STBCC_GRID_COUNT_X_LOG2-3)) + +#ifndef STBCC_CLUSTER_SIZE_X_LOG2 +#define STBCC_CLUSTER_SIZE_X_LOG2 5 +#endif + +#ifndef STBCC_CLUSTER_SIZE_Y_LOG2 +#define STBCC_CLUSTER_SIZE_Y_LOG2 5 +#endif + +#define STBCC__CLUSTER_SIZE_X (1 << STBCC_CLUSTER_SIZE_X_LOG2) +#define STBCC__CLUSTER_SIZE_Y (1 << STBCC_CLUSTER_SIZE_Y_LOG2) + +#define STBCC__CLUSTER_COUNT_X_LOG2 (STBCC_GRID_COUNT_X_LOG2 - STBCC_CLUSTER_SIZE_X_LOG2) +#define STBCC__CLUSTER_COUNT_Y_LOG2 (STBCC_GRID_COUNT_Y_LOG2 - STBCC_CLUSTER_SIZE_Y_LOG2) + +#define STBCC__CLUSTER_COUNT_X (1 << STBCC__CLUSTER_COUNT_X_LOG2) +#define STBCC__CLUSTER_COUNT_Y (1 << STBCC__CLUSTER_COUNT_Y_LOG2) + +#if STBCC__CLUSTER_SIZE_X >= STBCC__GRID_COUNT_X || STBCC__CLUSTER_SIZE_Y >= STBCC__GRID_COUNT_Y + #error "STBCC_CLUSTER_SIZE_X/Y_LOG2 must be smaller than STBCC_GRID_COUNT_X/Y_LOG2" +#endif + +// worst case # of clumps per cluster +#define STBCC__MAX_CLUMPS_PER_CLUSTER_LOG2 (STBCC_CLUSTER_SIZE_X_LOG2 + STBCC_CLUSTER_SIZE_Y_LOG2-1) +#define STBCC__MAX_CLUMPS_PER_CLUSTER (1 << STBCC__MAX_CLUMPS_PER_CLUSTER_LOG2) +#define STBCC__MAX_CLUMPS (STBCC__MAX_CLUMPS_PER_CLUSTER * STBCC__CLUSTER_COUNT_X * STBCC__CLUSTER_COUNT_Y) +#define STBCC__NULL_CLUMPID STBCC__MAX_CLUMPS_PER_CLUSTER + +#define STBCC__CLUSTER_X_FOR_COORD_X(x) ((x) >> STBCC_CLUSTER_SIZE_X_LOG2) +#define STBCC__CLUSTER_Y_FOR_COORD_Y(y) ((y) >> STBCC_CLUSTER_SIZE_Y_LOG2) + +#define STBCC__MAP_BYTE_MASK(x,y) (1 << ((x) & 7)) +#define STBCC__MAP_BYTE(g,x,y) ((g)->map[y][(x) >> 3]) +#define STBCC__MAP_OPEN(g,x,y) (STBCC__MAP_BYTE(g,x,y) & STBCC__MAP_BYTE_MASK(x,y)) + +typedef unsigned short stbcc__clumpid; +typedef unsigned char stbcc__verify_max_clumps[STBCC__MAX_CLUMPS_PER_CLUSTER < (1 << (8*sizeof(stbcc__clumpid))) ? 1 : -1]; + +#define STBCC__MAX_EXITS_PER_CLUMP (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 +// 2^19 * 2^6 => 2^25 exits => 2^26 => 64MB for 1024x1024 + +typedef unsigned char stbcc__verify_max_exits[STBCC__MAX_EXITS_PER_CLUMP <= 256]; + +typedef struct +{ + unsigned short clump_index:12; + signed short cluster_dx:2; + signed short cluster_dy:2; +} stbcc__relative_clumpid; + +typedef union +{ + struct { + unsigned int clump_index:12; + unsigned int cluster_x:10; + unsigned int cluster_y:10; + } f; + unsigned int c; +} stbcc__global_clumpid; + +// rebuilt cluster 3,4 + +// what changes in cluster 2,4 + +typedef struct +{ + stbcc__global_clumpid global_label; + unsigned char num_adjacent; + stbcc__relative_clumpid adjacent_clumps[STBCC__MAX_EXITS_PER_CLUMP]; +} stbcc__clump; + +typedef struct +{ + unsigned int num_clumps; + stbcc__clump clump[STBCC__MAX_CLUMPS_PER_CLUSTER]; +} stbcc__cluster; + +struct st_stbcc_grid +{ + int w,h,cw,ch; + unsigned char map[STBCC__GRID_COUNT_Y][STBCC__MAP_STRIDE]; // 1K x 1K => 1K x 128 => 128KB + stbcc__clumpid clump_for_node[STBCC__GRID_COUNT_Y][STBCC__GRID_COUNT_X]; // 1K x 1K x 2 = 2MB + stbcc__cluster cluster[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // 1K x 1K x 0.5 x 64 x 2 = 64MB +}; + +int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) +{ + stbcc__global_clumpid label1, label2; + stbcc__clumpid c1 = g->clump_for_node[y1][x1]; + stbcc__clumpid c2 = g->clump_for_node[y2][x2]; + int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); + int cy1 = STBCC__CLUSTER_Y_FOR_COORD_Y(y1); + int cx2 = STBCC__CLUSTER_X_FOR_COORD_X(x2); + int cy2 = STBCC__CLUSTER_Y_FOR_COORD_Y(y2); + if (c1 == STBCC__NULL_CLUMPID || c2 == STBCC__NULL_CLUMPID) + return 0; + label1 = g->cluster[cy1][cx1].clump[c1].global_label; + label2 = g->cluster[cy2][cx2].clump[c2].global_label; + if (label1.c == label2.c) + return 1; + return 0; +} + +int stbcc_query_grid_open(stbcc_grid *g, int x, int y) +{ + return STBCC__MAP_OPEN(g, x, y) != 0; +} + +unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y) +{ + stbcc__clumpid c = g->clump_for_node[y][x]; + int cx = STBCC__CLUSTER_X_FOR_COORD_X(x); + int cy = STBCC__CLUSTER_Y_FOR_COORD_Y(y); + return g->cluster[cy][cx].clump[c].global_label.c; +} + +typedef struct +{ + unsigned char x,y; +} stbcc__tinypoint; + +typedef struct +{ + stbcc__tinypoint parent[STBCC__CLUSTER_SIZE_Y][STBCC__CLUSTER_SIZE_X]; // 32x32 => 2KB + stbcc__clumpid label[STBCC__CLUSTER_SIZE_Y][STBCC__CLUSTER_SIZE_X]; +} stbcc__cluster_build_info; + +static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy); +static void stbcc__remove_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy); +static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy); + +static stbcc__global_clumpid stbcc__clump_find(stbcc_grid *g, stbcc__global_clumpid n) +{ + stbcc__global_clumpid q; + stbcc__clump *c = &g->cluster[n.f.cluster_y][n.f.cluster_x].clump[n.f.clump_index]; + + if (c->global_label.c == n.c) + return n; + + q = stbcc__clump_find(g, c->global_label); + c->global_label = q; + return q; +} + +typedef struct +{ + unsigned int cluster_x; + unsigned int cluster_y; + unsigned int clump_index; +} stbcc__unpacked_clumpid; + +// @OPTIMIZE: pass in these parameters unpacked, not packed +static void stbcc__clump_union(stbcc_grid *g, stbcc__unpacked_clumpid m, int x, int y, int idx) +{ + stbcc__clump *mc = &g->cluster[m.cluster_y][m.cluster_x].clump[m.clump_index]; + stbcc__clump *nc = &g->cluster[y][x].clump[idx]; + stbcc__global_clumpid mp = stbcc__clump_find(g, mc->global_label); + stbcc__global_clumpid np = stbcc__clump_find(g, nc->global_label); + + if (mp.c == np.c) + return; + + g->cluster[mp.f.cluster_y][mp.f.cluster_x].clump[mp.f.clump_index].global_label = np; +} + +static void stbcc__build_connected_components_for_clumps(stbcc_grid *g) +{ + int i,j,k,h; + + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { + stbcc__cluster *cluster = &g->cluster[j][i]; + for (k=0; k < (int) cluster->num_clumps; ++k) { + stbcc__global_clumpid m; + m.f.clump_index = k; + m.f.cluster_x = i; + m.f.cluster_y = j; + assert((int) m.f.clump_index == k && (int) m.f.cluster_x == i && (int) m.f.cluster_y == j); + cluster->clump[k].global_label = m; + } + } + } + + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { + stbcc__cluster *cluster = &g->cluster[j][i]; + for (k=0; k < (int) cluster->num_clumps; ++k) { + stbcc__clump *clump = &cluster->clump[k]; + stbcc__unpacked_clumpid m; + m.clump_index = k; + m.cluster_x = i; + m.cluster_y = j; + for (h=0; h < clump->num_adjacent; ++h) { + unsigned int clump_index = clump->adjacent_clumps[h].clump_index; + unsigned int x = clump->adjacent_clumps[h].cluster_dx + i; + unsigned int y = clump->adjacent_clumps[h].cluster_dy + j; + stbcc__clump_union(g, m, x, y, clump_index); + } + } + } + } + + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { + stbcc__cluster *cluster = &g->cluster[j][i]; + for (k=0; k < (int) cluster->num_clumps; ++k) { + stbcc__global_clumpid m; + m.f.clump_index = k; + m.f.cluster_x = i; + m.f.cluster_y = j; + stbcc__clump_find(g, m); + } + } + } +} + +void stbcc_update_grid(stbcc_grid *g, int x, int y, int solid) +{ + int cx,cy; + + if (!solid) { + if (STBCC__MAP_OPEN(g,x,y)) + return; + } else { + if (!STBCC__MAP_OPEN(g,x,y)) + return; + } + + cx = STBCC__CLUSTER_X_FOR_COORD_X(x); + cy = STBCC__CLUSTER_Y_FOR_COORD_Y(y); + + stbcc__remove_connections_to_adjacent_cluster(g, cx-1, cy, 1, 0); + stbcc__remove_connections_to_adjacent_cluster(g, cx+1, cy, -1, 0); + stbcc__remove_connections_to_adjacent_cluster(g, cx, cy-1, 0, 1); + stbcc__remove_connections_to_adjacent_cluster(g, cx, cy+1, 0,-1); + + if (!solid) + STBCC__MAP_BYTE(g,x,y) |= STBCC__MAP_BYTE_MASK(x,y); + else + STBCC__MAP_BYTE(g,x,y) &= ~STBCC__MAP_BYTE_MASK(x,y); + + stbcc__build_clumps_for_cluster(g, cx, cy); + + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, -1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0,-1); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0, 1); + + stbcc__add_connections_to_adjacent_cluster(g, cx-1, cy, 1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx+1, cy, -1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy-1, 0, 1); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy+1, 0,-1); + + stbcc__build_connected_components_for_clumps(g); +} + +size_t stbcc_grid_sizeof(void) +{ + return sizeof(stbcc_grid); +} + +void stbcc_init_grid(stbcc_grid *g, unsigned char *map, int w, int h) +{ + int i,j,k; + assert(w % STBCC__CLUSTER_SIZE_X == 0); + assert(h % STBCC__CLUSTER_SIZE_Y == 0); + assert(w % 8 == 0); + + g->w = w; + g->h = h; + g->cw = w >> STBCC_CLUSTER_SIZE_X_LOG2; + g->ch = h >> STBCC_CLUSTER_SIZE_Y_LOG2; + + for (j=0; j < h; ++j) { + for (i=0; i < w; i += 8) { + unsigned char c = 0; + for (k=0; k < 8; ++k) + if (map[j*w + (i+k)] == 0) + c |= (1 << k); + g->map[j][i>>3] = c; + } + } + + for (j=0; j < g->ch; ++j) + for (i=0; i < g->cw; ++i) + stbcc__build_clumps_for_cluster(g, i, j); + + for (j=0; j < g->ch; ++j) { + for (i=0; i < g->cw; ++i) { + stbcc__add_connections_to_adjacent_cluster(g, i, j, -1, 0); + stbcc__add_connections_to_adjacent_cluster(g, i, j, 1, 0); + stbcc__add_connections_to_adjacent_cluster(g, i, j, 0,-1); + stbcc__add_connections_to_adjacent_cluster(g, i, j, 0, 1); + } + } + + stbcc__build_connected_components_for_clumps(g); + + for (j=0; j < g->h; ++j) + for (i=0; i < g->w; ++i) + assert(g->clump_for_node[j][i] <= STBCC__NULL_CLUMPID); +} + + +static void stbcc__add_clump_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) +{ + stbcc__clump *clump; + + int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); + int cy1 = STBCC__CLUSTER_Y_FOR_COORD_Y(y1); + int cx2 = STBCC__CLUSTER_X_FOR_COORD_X(x2); + int cy2 = STBCC__CLUSTER_Y_FOR_COORD_Y(y2); + + stbcc__clumpid c1 = g->clump_for_node[y1][x1]; + stbcc__clumpid c2 = g->clump_for_node[y2][x2]; + + stbcc__relative_clumpid rc; + + assert(cx1 != cx2 || cy1 != cy2); + assert(abs(cx1-cx2) + abs(cy1-cy2) == 1); + + // add connection to c2 in c1 + + rc.clump_index = c2; + rc.cluster_dx = x2-x1; + rc.cluster_dy = y2-y1; + + clump = &g->cluster[cy1][cx1].clump[c1]; + assert(clump->num_adjacent < STBCC__MAX_EXITS_PER_CLUMP); + clump->adjacent_clumps[clump->num_adjacent++] = rc; +} + +static void stbcc__remove_clump_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) +{ + stbcc__clump *clump; + int i; + + int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); + int cy1 = STBCC__CLUSTER_Y_FOR_COORD_Y(y1); + int cx2 = STBCC__CLUSTER_X_FOR_COORD_X(x2); + int cy2 = STBCC__CLUSTER_Y_FOR_COORD_Y(y2); + + stbcc__clumpid c1 = g->clump_for_node[y1][x1]; + stbcc__clumpid c2 = g->clump_for_node[y2][x2]; + + stbcc__relative_clumpid rc; + + assert(cx1 != cx2 || cy1 != cy2); + assert(abs(cx1-cx2) + abs(cy1-cy2) == 1); + + // add connection to c2 in c1 + + rc.clump_index = c2; + rc.cluster_dx = x2-x1; + rc.cluster_dy = y2-y1; + + clump = &g->cluster[cy1][cx1].clump[c1]; + + for (i=0; i < clump->num_adjacent; ++i) + if (rc.clump_index == clump->adjacent_clumps[i].clump_index && + rc.cluster_dx == clump->adjacent_clumps[i].cluster_dx && + rc.cluster_dy == clump->adjacent_clumps[i].cluster_dy) + break; + + if (i < clump->num_adjacent) + clump->adjacent_clumps[i] = clump->adjacent_clumps[--clump->num_adjacent]; + else + assert(0); +} + +static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy) +{ + unsigned char connected[STBCC__MAX_CLUMPS_PER_CLUSTER/8] = { 0 }; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + int step_x, step_y=0, i, j, k, n; + + if (cx < 0 || cx >= g->cw || cy < 0 || cy >= g->ch) + return; + + if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) + return; + + assert(abs(dx) + abs(dy) == 1); + + if (dx == 1) { + i = STBCC__CLUSTER_SIZE_X-1; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dx == -1) { + i = 0; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dy == -1) { + i = 0; + j = 0; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else if (dy == 1) { + i = 0; + j = STBCC__CLUSTER_SIZE_Y-1; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else { + assert(0); + } + + for (k=0; k < n; ++k) { + if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { + stbcc__clumpid c = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (connected[c>>3] & (1 << (c & 7)))) { + connected[c>>3] |= 1 << (c & 7); + stbcc__add_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); + } + } + i += step_x; + j += step_y; + } +} + +static void stbcc__remove_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy) +{ + unsigned char disconnected[STBCC__MAX_CLUMPS_PER_CLUSTER/8] = { 0 }; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + int step_x, step_y=0, i, j, k, n; + + if (cx < 0 || cx >= g->cw || cy < 0 || cy >= g->ch) + return; + + if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) + return; + + assert(abs(dx) + abs(dy) == 1); + + if (dx == 1) { + i = STBCC__CLUSTER_SIZE_X-1; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dx == -1) { + i = 0; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + } else if (dy == -1) { + i = 0; + j = 0; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else if (dy == 1) { + i = 0; + j = STBCC__CLUSTER_SIZE_Y-1; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + } else { + assert(0); + } + + for (k=0; k < n; ++k) { + if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { + stbcc__clumpid c = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (disconnected[c>>3] & (1 << (c & 7)))) { + disconnected[c>>3] |= 1 << (c & 7); + stbcc__remove_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); + } + } + i += step_x; + j += step_y; + } +} + +static stbcc__tinypoint stbcc__incluster_find(stbcc__cluster_build_info *cbi, int x, int y) +{ + stbcc__tinypoint p,q; + p = cbi->parent[y][x]; + if (p.x == x && p.y == y) + return p; + q = stbcc__incluster_find(cbi, p.x, p.y); + cbi->parent[y][x] = q; + return q; +} + +static void stbcc__incluster_union(stbcc__cluster_build_info *cbi, int x1, int y1, int x2, int y2) +{ + stbcc__tinypoint p = stbcc__incluster_find(cbi, x1,y1); + stbcc__tinypoint q = stbcc__incluster_find(cbi, x2,y2); + + if (p.x == q.x && p.y == q.y) + return; + + cbi->parent[p.y][p.x] = q; +} + +static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) +{ + stbcc__cluster *c; + stbcc__cluster_build_info cbi; + int label=0; + int i,j; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + + // set initial disjoint set forest state + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + cbi.parent[j][i].x = i; + cbi.parent[j][i].y = j; + } + } + + // join all sets that are connected + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + // check down only if not on bottom row + if (j < STBCC__CLUSTER_SIZE_Y-1) + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) + if (STBCC__MAP_OPEN(g,x+i,y+j) && STBCC__MAP_OPEN(g,x+i ,y+j+1)) + stbcc__incluster_union(&cbi, i,j, i,j+1); + // check right for everything but rightmost column + for (i=0; i < STBCC__CLUSTER_SIZE_X-1; ++i) + if (STBCC__MAP_OPEN(g,x+i,y+j) && STBCC__MAP_OPEN(g,x+i+1,y+j )) + stbcc__incluster_union(&cbi, i,j, i+1,j); + } + + // label all non-empty leaders + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + stbcc__tinypoint p = cbi.parent[j][i]; + if (p.x == i && p.y == j) + if (STBCC__MAP_OPEN(g,x+i,y+j)) + cbi.label[j][i] = label++; + else + cbi.label[j][i] = STBCC__NULL_CLUMPID; + } + } + + // label all other nodes + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x != i || p.y != j) { + if (STBCC__MAP_OPEN(g,x+i,y+j)) + cbi.label[j][i] = cbi.label[p.y][p.x]; + } + } + } + + c = &g->cluster[cy][cx]; + c->num_clumps = label; + for (i=0; i < label; ++i) + c->clump[i].num_adjacent = 0; + + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + g->clump_for_node[y+j][x+i] = cbi.label[j][i]; // @OPTIMIZE: remove cbi.label entirely + assert(g->clump_for_node[y+j][x+i] <= STBCC__NULL_CLUMPID); + } +} + +#endif // STB_CONNECTED_COMPONENTS_IMPLEMENTATION diff --git a/tools/README.list b/tools/README.list index 5ad58a1..b5c3e5b 100644 --- a/tools/README.list +++ b/tools/README.list @@ -14,5 +14,6 @@ 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 From d32dc9f43a35ad23f81f422109b7e2b6a3690e27 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 15 Apr 2016 21:40:37 -0700 Subject: [PATCH 320/522] add todo list, try to compile as C++ (untested), tweak data structure --- stb_connected_components.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index 7b91d42..2ba78a3 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -1,4 +1,4 @@ -// stb_connected_components - v0.90 - public domain connected components on grids +// stb_connected_components - v0.91 - public domain connected components on grids // http://github.com/nothings/stb // // Finds connected components on 2D grids for testing reachability between @@ -23,6 +23,19 @@ // license: you are granted a perpetual, irrevocable license to copy, modify, // publish, and distribute this file as you see fit. // +// +// TODO: +// - test C++ compile +// - better API documentation +// - internals documentation (including algorithm) +// - try re-integrating naive algorithm & compare performance +// - batching (keep data structure w/ dirty clusters) +// - function for setting a grid of squares at once (just use batching) +// - shrink data by storing only, say, 2X max exits +// (instead of max exits per clump), and repack cluster +// if it runs out (possibly by just rebuilding from scratch, +// could even use dirty-cluster data structure) +// should reduce 1Kx1K from ~66MB to ~8MB #ifndef INCLUDE_STB_CONNECTED_COMPONENTS_H #define INCLUDE_STB_CONNECTED_COMPONENTS_H @@ -32,6 +45,10 @@ typedef struct st_stbcc_grid stbcc_grid; +#ifdef __cplusplus +extern "C" { +#endif + ////////////////////////////////////////////////////////////////////////////////////////// // // initialization @@ -69,6 +86,10 @@ extern int stbcc_query_grid_open(stbcc_grid *g, int x, int y); // small, you'll need a hash table or something to remap it (or just use extern unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y); +#ifdef __cplusplus +} +#endif + #endif // INCLUDE_STB_CONNECTED_COMPONENTS_H #ifdef STB_CONNECTED_COMPONENTS_IMPLEMENTATION @@ -148,7 +169,7 @@ typedef union typedef struct { stbcc__global_clumpid global_label; - unsigned char num_adjacent; + unsigned short num_adjacent; stbcc__relative_clumpid adjacent_clumps[STBCC__MAX_EXITS_PER_CLUMP]; } stbcc__clump; From 435e0c757ce93c7238de1fc2e2518f9aef48dec6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 15 Apr 2016 21:41:08 -0700 Subject: [PATCH 321/522] update stbcc --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 05c9d25..a7c7e01 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ library | lastest version | category | LoC | description **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**stb_connected_comp...** | 0.90 | misc | 653 | incrementally compute reachability on grids +**stb_connected_comp...** | 0.91 | misc | 674 | incrementally compute reachability on grids **stb.h** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 -Total lines of C code: 47467 +Total lines of C code: 47488 FAQ From 1392344cdde1529b1ea1163e258e721b0f3d13b3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 09:14:39 -0700 Subject: [PATCH 322/522] include stb_connected_components.h in main stb compile tests, add test app --- data/map_01.png | Bin 0 -> 26064 bytes data/map_02.png | Bin 0 -> 3243 bytes data/map_03.png | Bin 0 -> 8747 bytes tests/stb.dsp | 6 +++++- tests/test_c_compilation.c | 5 +++++ tests/test_cpp_compilation.cpp | 5 +++++ tests/test_truetype.c | 4 ++-- 7 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 data/map_01.png create mode 100644 data/map_02.png create mode 100644 data/map_03.png diff --git a/data/map_01.png b/data/map_01.png new file mode 100644 index 0000000000000000000000000000000000000000..a2be8a0dc73c2be249a6250034362ccaef2644ea GIT binary patch literal 26064 zcmV(*K;FNJP)@|Pz+3j11l!{Kuln!Vf?_n z*jqAVAIV4evtv2rh(e6s>*q)U6u8Jx9mERnpetYbC6C-OJUukJ>d zKmZ2}31B1MLW1Yz&qSV1-hBgk;QWdVd0Uw!0KnD`2Lu6V;3Z;80j>lt1#bgKUq`G1 zKD?5G&F|N`Abg^!k@1!i0KhvidUoRj06(8y)C9QFyp8w(`0~#+6e;_Q~UkPWS=2x2h6 z|MRs|jv4|y`78jb{Yb%Eh+w|7NMFMzLPHF|%n`uqbpV0~1#d0E{TSes_=Ol!Rc!tr zN`_5$Y(wV2(ap^87BhPWVDDjoOL!asg)4xt`g*1z|KvJvAD`5mEFvy|2w+hOum)@a zHcQshW+eq<`o}&K? z$oE`;a#|oIBEoXb+snBEel^>MZ7L)Wc!n@mk|20HNCE6m=q(Ps1Bu+{u@jaXs{koD zM)Ee2aX&oyz#{k z426G>QsS2Thm2TKYWakl`l zt|pJeU}ax$!7E=aw)n3oW-(TgtEK=cLgOX8ZJ5nS!~i!(oh@*LBxE8!npOA$?6Ywp zL-Kzb1$|u*+w|=cKu6-l2-e>banxvLNsU|HHY7m61w>t=z)RpZx|O^g9D^>$&O>2T z+S3J=wRPSO6aYp;DEZKK794qfS+bC~np^`ghZsQor0VP&INHQ}+qxb+?JLl5?1R5? zul0#sR=gjRKzyR9~0cJepZPdVbXaG-( zU(&)r*6yVJRY%rJ-63DhO-AHHTLXCgLvKP$SHJ;#mq1 zy8?v3bCw)+*yV7cxC8681W}B~bNIBsX|7Z`Wdj!YfXvY3OAwuLcgTb$fdjy5%?34OX@))xkZVldvP*wUt@90&mOXr>1OSV&3)X;a z&Lz1*YC70B^ZqbllyUEQcE%s;gIvc{_yoW#5NrVg{#HobmVS$Gh^x;7@SYI9JH){! z1bF2YVoEM>5gFeYYbh+WKKqVi_?`@AJ(f_>%~=cp`JJcgA&{|$;>h!xcHjUT0D#s2 zJFMgKst*8yE`Ey%T(QK{ho`j=OrklldVP1Zw zyCd>w=)vDH(P;lFB(PTSc%cnTqyRYARcQKkIyj=2kWsEn71IQNpo!BeL4pK(kVl3R z?4d;!@`u{Fb3SONE>Mj=Nf*7 ze)NGQr_DJU%``IB77-@KL2}M(fPoLu!~0{)4tR87Fia!Yf&!JW){2S^#IQ>b+u4&o zGZjq_Ph*Zi=K8%{aR^n~J*J%BB)FHsq5DuT8E3O0vFTFeL%%s}+w zW8dR_95_jv0$7F6=&=HpqSsqIdju3%2AFvXaP_fI^VN5Dw7^DhD=q*o3mzaL?v7oJ z4_MGWE+eQW6W$uOCrhS)wRRQ>eMN#pt zF_R@;;@)=ERkGe6$Cv{+E5>h1kjarc&uMn0!RStBBn((BfbRE`6^|-A9;MK;CS!gcIkwy%1p+Z8=K}I0r4pQa(um4CcX!nAP-vE za?b#_EWYm_o$)#y{AM(J^2Jupau#E6px|XR6v^k<9P(I#ielXnz%T#(u9WujaSVz8 z4Zt@8YljD@E^;HCxkT%bGU^D=phF_03 z0$xL}V<7N_u>gBp3=;woB9??0bWMPTh66(O``p+)0|2Ke;Buh>`v8d#;ThknsqpC| z0Jedv&MwebjAPhfrWXM02n`aVQ~Vd1!rC^Mzz!5}&=6n_!0}ACvo&Y+ZV?1O2mn87 z5C~unii~kYOvdah3NDD*a0TE}1FvjBEBf4mSObvjYrZz8LdVI>0ObC(ylPHxPy8YP zx*@=OV4ol+p~)6p0Njva_njG;N}N>e7#?Uma}T!JGHp{V%n`)B^S^);ZdrU+m2`;G zccuWy$4tTSua_R_HCKQmV2uOVqs``h03R0GMu*E$b;CA3#0Kzm!*q5Maj8iq-qVHO zJu_;P)jUGDjP1et=H0N6*gXXT&61G90JI~7Ex1yFfIUxk2%v|pc>Y~Zsw#hs_B=@X zR|~HXaan_dGcfD;v<0w~oHd`O;D!u`(hL69)M_WI5#>X!X$v4I>C}VIafr(apva2W zvgSHD0E9j@#1WXH?XV>yy;5H6 z4#JlJh}URW(d=*B?ocPyx@C$s)1C_RGzM+jT1aT95IoS8M9LLFA!6zT55>}KTh(1O zuuy1BkFsY3RUbb-0GZEYrH}k{ov2%Z$u*BTGe7k?!t-73}Q$-b9cA!F|PiCC1(L3 zK~UuGE}QiCb(vzw9{~xKM%vzZ^EnWFkUa>1ws!p`Xb7v9__sbO1|k!4>Ie{oyiN*0 z<~K571u&4O%jhN0C>oDi5El?#@U4yjVUXAJBL5+x;$kq$1S~G5)?ksdgY|#>ERX;p zvsOGHsyg`Tgz&465={@sO{Z)$`!~Qk5HC5W|+uBHn`eN|J)TIX(xe8wqu14 zw;7&>joQbmO&|YC@mfMUt!&L|IOt!*6Td@99S^o8O(c*9SNa;jYHl81sar~{(Dd`n z3@#`J1PvY8`!SJ664+`ql-MB2fPzp1mMI)^5&z$fLgDxp&DvGfG}p_M*&geGbenhk^blLu87u-|ivoz)ak?P#f#}#VRfF1=1Xt6}xNjXNF;XhBzoFxd$MA84VD9 zg>8hh#ltb@HxD$37}#cn{l%kn#sJdsM*ANz2n`&`4Woqt!dg|WNLT~=->n-;JjOUA zz|c)j>N3JFCOG#NtJB3Dcx0mYi?oIwRZy7Y;cP$^YrkZ`XifT!UU zE*IMB_QqHLoi6?ifDu- z=qA>{A5!C$Z%Y9MB>UoA#2^9WF@O!=EBDC&upf>*%|xzI-EQHvbw7p6wOTeI10u_& zSz8M!ks9E74?YW*B*1enm`+YN_war%)>%C~DH32F?tQ0agYCwu+4VEv*olEg{ZSt2 zIO+?|KB|D@c&V|6RV?n$01t=(UzD|8n^^7a?HXq@J>Svv@+~>}hqWdFUI0j83k^Vw z)&NM!G4L8d!450nnIAc#A49N>IaO6aX745V1Tjz)rRGRKKj0I(GwV2}3p)h#a}fi| zkAR$81CU3^|33iP1&RPb1|IeZMEv8VtcVwH#yMSR*aB}J0bKcNs~j^THo##D_m~67 zu#7|l5}vQJwZlK|FWuAN8?tl@fX#SqzX~}Mc*GKU0GD?@V<$!YBz^n?2*^T!Ict^s zxdzTaR(2rn{`Gr|Py|HuQ*cu*Rfah4Xu%@%QB)PNVAa!S3K#1$LS_|x+`g$Jd|Sps zU#ms~w_ls(pymJ)(0AEIiTEXqAJU72`F`0`h_Id&vp*zry|iJr*WC=WC(nW+rVk%9 zALXz)zE3Rxo(@|^)YGiO`m;}lo}rfw_^V)?+*O7EMFJrKF(BbNcfx8$xFM<*HqgsJ z@&uj(YZyR6%-!(fhs4o9-N5G-Pa=S=0tys>g#+^NuRJD+h0=f|SB?u>1v!{9`>Itu z2k>oGmY@mYCOFWg-;sT~HfM}Od?E_^nE@AA4~<+Vz5?+5EzQ^YeE=UrC!371h=zBA z%6kBw)|khj8zC#c{`&y(ndXjcj7?!B#sH`&UTUGi2f!kU0DQ$=2^l67=0g!E*fjvE zZtKb{R{x}NZj@`6Ey05L*0vWTbVB}z+pS412$#!t4EGZQ4FR7mcKcuin6X>yU$ z$C=d-k(9laL5hHkDE_)?nBtAQ*?@od!h6^0;kAe(5=hxxj>-%)1>q&9xB`TmtVkSj zY!&2Dk5ztO2;4vhx)u&7tPZkS(hwjDS&e+pa4rFoBLL!PL4&jU3j7ux!2>c z2Ac}aN<@@geG)i%_F{6VX^|gc6$w30rHef3cVCyD=)}c4WC?{ zfOuVRm(mLjzwBS00S74{qxy?4x10xn<~HRQsxG*|rrZTlM33LlyTGo7#|7Mb&j*2n z4B#dPjzDDqCVb{;U=29hu!pkhf?V<15t@}qmc>N>1mHkjeGwZTeBUcN1bl$JUR>mz z1;Pav0hcLX0zjSs@g;X8Oz9&qB!Q-4^AYiKR4(obRa3&4yKzu# z4W^4@MMdC~u%tjYmTvc1m6_0T@YsB<>ia%s8nRX_CjkV2VpX;nB(XUTlGIIwU&cXv0TMI-YiQKm5#S+jH5!-WgD;874x}L3Ty)sI01{NLH0jw!64#y zgk}&QOT3I&V4=(#;&q+>zt)EXf1M6q2>4 z-xBt?8^6bymJA?p@%Jm6pMse_HJj5xu9DR1v2r$3%K&;O7%yIEG-Ovqg431&8||_n zFX_pieXr&zLqzD;oGS@DZKG2BkZsrl2?=i(x;da8LC9gH#p@uQyKDACTC8u9F>JKp3lZJyL=+=i zkW)bR2NV8;wE3YgVtUv~B(pvXok?H;H?9EtOP3T(JQR$B-Xip`Z1J>rBXA)!0EKJ} z{m)$~K-grwzCBmNTaCTU%xQ2H@k|>ZY-x>30XCCu*nqh(z(WX|QAJD_{(zXje6Vzb zs!HBgju{dndLrOnUK~s8zQN$8Bi5vkQYXD9W>sB#ao4Ph202}l;rJakW zJIQtQtZa+z#)V2}7jO+E*GS;HWkw=8kb_a3O{ONjcc|`eNUp3pP0n1i{v&jh-my0J>}}d;SPW zw-#TleKQMrLq-qfzyWS1~P;rn%VFU|y2o z6=6C{DG|Ck?q&Bdl;UN$yl+d}^1M1xH%M+FBf4njQ~r$xQWO9N5E2lthoBKzO^7$B z@R7Y2HhAXey4svr)WyEATeS&71Y8o6)(V>s%Ic&8JY9Ez*DX$b|&h)ECkX zbqbg{FLdPJ0grEdoz3gFowf<0F2$pqq#-TxK!w z8n8}2$HBC+L28eg1gj{}+blGIVg_eNINUIqT>}>I4A-s_oHvUIh^mv>^y8TSRaXJ6 zX32s}xyr3V_t+)?BJ87C%R7gFC97PLWXaE#3Xt9n;vd>r%@oZCq38$z#K6Bq;u97}4%>xkjj+#w7$EA;K==R|L>vyUpnre{F+^1tgcQ-LOEUbl7*HmY|Ev6$%WZJRC2O|H|OnP)w6=9qD&+7*WD+mCh>Q1`YNrli<<9 zlEs5Mw95b~XA3Q*)7lB0ys3e8I`ET;EAMl>5SI)CPEh*t9q#i}!)f8Ou{xw=d9|D( zf5p(`6o8E*6d^4H9Py2j%1TAPp7xAsO-w`=0>vO{cr?7~lSu#{1bF~@PA5L}nWAA9 zlw?NHAOQ-woI_mzI-mc? zAOqiisjpN(ATPVO(^wz{Y|CG@>pJ~rgT}y2BLOZU5N5Eb#_-Rg&agWGM104)p#zWr zF@(LFEaz}z`r0_40Qi#qY4?H5&w2DG}{ zj-EthK%mJf`6UrznrSRsTN!>{{!Lw1oql_+=~jXx^g6(mp@S43@C_wb;s;2de7x0S z5fbREC39S@h*#U$mk|T<)M{Nd)=siGovwN2 z1IUnygHzhb2^-z#M0xL?RJ8?=f&xIWTVGs{Jw2>Rn=%IA+tX-Zk^H*4uf4}#`e}Lb zXC8mu{yG4!0TB-?gRs$V*WG0sC8|5Jxd)IS=;Ia~(Ir0n*#oPw!-gmWh!Po8i+Eia zAVZ~e^EkE|a)2Vi*0Mtfpc+X|(XM|`NG2iq_6<7FI~+r%;Og-{1-f2Z{w#(2V-tDl z<6tA|cp2ay_qU{o4}ep^TOex!Y;8b@9gQ5Mta>sRa81Wxo#{WJk6jIE#u@0&V@z*` zlDM1Nxzj4!?1>`x!DE1p0zCbLEzvT>&n6?YT&b$#7ShlPg~K{Pq}hY(u@u<{5pF*} z%%hB`*QIO#78zHazZrkE+X$P4VH6Pnxg}=FOec7C1q_*Q(wTfkO1s$0&?}z-YBCaFdiV>&jn>S1@%a)e4A)3tN-d1y~GgqZM|*Wn`@y%39L3- zK;+J{5>bF$s#7w&@)M1m(iwt`oBb>p;sy*KA5y~`{wP6Hd_5{0#o-n;I9wTp>| zfkfqcuBh}=DJq4g5Kx)JQSqi5!iI-C)=L5%F3yK=Ggg<|@F z!L#OgF}jMbB`(&l{q0vGx|uPRhX6V?)CiTTlvB{)X@X=NF)>}8^jCQVbYfB@OntHj z<~_r&y5=k1?1-MMgSQb(7wA z1Q<8mBH8a51)@9h{tL39G()yKU4W#=V<)({`Km;|W9UBOBGi&Go-@1qUR*nTlApv# zR>8+GOh&)G^ge575X6#kVt`o+ATEJ|enK~}dl7&5sIyDSI17N_Gy!C_4m0N)XWd^& zMiDcsAly4Q1jGQdj&MOO9WZ@d(n2B`MQ#CTOc|UP0lfr1bxb`29CAYo$rKdUUM*uL zIoC`j%c?X;kR~(`(*)2UG#J8nX^4b|2RzYE+@ydE{FMsc(s~PQBn(mLbth7`lMa#I zC7>eM!o`^vge&az{+~1xd8uxl3Llp|LOLm(ZeCw*W>Q6&E>JYk-8S!VSmDmAzpatb zO@6>5@{AC420P{b5dV;IwirV;+xH%AytL`)cKZ7)0q{u27ye^MfZ)1s{&D^+3d;Ob z3I{kuos+eQtW-!Ec!!yImsvofpHb}d90YXBo z;dLTz|APkSVzHwIHLP$1;Q8>%C1TCE)j&VmStb#4q2W1T)pg3oO@9EZ0A$KE*7~pg zN~sX!)ljmBK+v1=IGdyckBFB`nt^2>01`_@U*!i!I(tFW%hlw7q}5FYko82uSzV-D z{rys+9^}{_Dy(YzIf>vex@wSN4vF&+J-k<5o-s`Joa1c(pZPpSNr2-m_@!C1qO$!N+p6^-LVBiAOL^qRy4Yb9V}!NX8LC9)dkqCJHm`M`9O>~FGane10fkl z0jxm`K-zRrMO`e}vbr}35CZXNcFWTPC6Pp!o8DM7A|BlgwZ}I!3KG!Cvg2dAxe%R& z(Ju2<1;_<}vQbRQcK{&1MBu(?++$D^$TqqbM67f_+riN`S6;&u zN6lB=yi*qleOYPvb+KsHJ0}#*7-%ja#*&gF4S-0e3Xu7&2;6G-Hp~QgqkCHVFMDTF z{zL&T+;{Rm6_Idw>Z)|e#;}T;uzzHTHEHz@Mc0ARtJq0ukMCq5I z`tZ;$xwcVw0RbR31+_zwBlex23HK%n;N}w4vNM9(!gJVNSorvf z(DV@mck+ghzyM&sXq*n;;K=E$EKwYkfp^#?q(5DN3mlFB3c{EYJx3%s6wNw|pqUNv z?$QFHHnTj4DEVm(n-3imZ9k|8tgbZ2=d_W%({~U+cE?Hgykw7zCVtaZfL@AsQe3HL3a(V+ zB7Yx;_rz|hXLTL$yXK=-+Y8_XlDMX>_(|mUw!ap(hCnz~0PAE&9K=sPkGfW4gX0fL zCnlFIox)CT0YifrUd}auBnHSK%&Mh1;KnM)1_~U`_i6ADv+)9+vA}4I=T0s3Y1wAfRb9|37!g zkgQ8*g0QK)7=R6Ob;RB?wcAU4zpXIubRV2A+NEO5D|>B8O%d|m-YuPi`N zeQH*}Pz+v^bdyBQRZ2|{5@w801gbvHA}-7KbV<`?hPsuM5Wpt@PN#OkHEnL^!T=mM zzbsmDEWj@}lvryZQ*8kfhS5=6Z%B2nTT^gdw{#hE08UsGH9K(C4%TNjmT=2dQahMV zM!SX6^%?nVw98X1wVz9YT)Zlz8=D_MEQn zs!$A^u=gSXF9sb`B6K;=5866#G=82^wG@n4P-3GVjXq}60LKwaj!(LR^BW}N1gh=} zBv4<-HtqZH{JE!biIc8zcb+3xnMN3d!M|jQ=sqPO*!)@Y2rjo+qI6fK0nUIwPd2d&alW5{Nqs2{gFsopl$T&gAHUVzU{auD3ym z%a4~GYrnK;y78ZHXA25+OL0%f0`s+@T~}GxaS%^wkX1|A2TcJ&GkO6;ov0BA<~TTS znJ|`aop)ZedQlf(v1qiT=@Hb*xcq)Or~Y$Ii5GPSs)6LOJz#)+>V%-^K!AO*nw=*! zDP&KgM4}1lBBRGq>MmQMM@-1R=7kJQ9Oq5D; z9ZbHDBo7gVe*iQ4>jM|p1VeT;qRy=h1{aLN#u$y^<{|7F*lt><%WPmiq?M-27F)T; zH4{l7WG&GU0iJ=NZZ8&Tvj-|iD~MIM1Ch$qWttCV?0%>6IScVUI0Us9_ZZ@#tFV%f zjUIb0RK07@frWw#Ae^3#yQG`$i0BBAmD7(YNeEuU)2BfGcl+uYwsJ*_#rLJ1i%HVb zN8~hxhCPS~U$$RTE8i3^WnU6o8aNucEF%0L>IRo3VNI!h5U*=WHb1X%5Ub}0iqh#5 zt(7ws2?V05#*3CM>cR79UiQ;w!Zy>8AEJ&(`ex?Eo7gL2o`-xzfk@zUj+yed2>=kU zW-DBUC$+dT!#ZF~Wh+8}h}QraZ1dBoTI2eq`mb?0zxssUbbsC0?!1kJZ<@3t!M+G6 zT1}hCW`72pehne7 zIq+2wI@dtK1&cXwp4O6O8j*4UXTa53UqQgSGd}-rJ!}E&C7mQ8aKQ#-u#F7>G)S80 z$SMHkm{Ub3Pb6{Th{rI+R;Z$mk{ji%ktcf_7&prB?XByk+vD z{tcH20MbUIyO~o{mH?md#V{|wzE28hunRV*kc%pl=Y-;gmjJ#S@k`M>J!X!JFj=k5 z!t!G6l#{--iIjQgyL`43O7~S#?R2FSC8*k;56-F<+y`PPKtR^CI`c`BZmD3c)FUwi z(WR?!1=h7EqLHP^%Wn10_5tPrGhFhJ8ribL0!J@e?Hc6(@N@wvP07~*P>@v}1hB>T z9}U>{3wfsx_N|kjx>Wor%b;oleyX>t~x65wd!NK%H`ea=J&NWbM(?r1Tm)J}7yxUzd%Dh&j3m-)ATlIbBgj*UG$XiNIA8SM!!FAsSb)dh4+fv-MN=&Da=N3@t z*u9Z#jjp`$3>mntP#CiQ^MW@CeG36t&BH_k@R4SCd=-L+p@#%P$=S%g=fb$H7G{8C zW|n(^<93G4l7f#0FeLP15IUSU;Dw&)bF0eCNUI@lrsNHW;6z2iRxUA|U| z#C2HGRhLE_tG*11MYMk}gM|VNAZOZnNR+dGP?XN0KS6TItp0wWLsP!m+{|wO|z(10DFjpP?b4D4O;+t&%Fee_c;xU zrbXtQq$Vkm5p6;?4e+7{Ajqx42M(PbM@4(MoF1P6!0gu0N9JW9=dP3Vsbk-D2toNa zJK+sroB&@}|2l)|TmcY{9ylmJM~$L63Z$M}$TpWxSHv{QQkJB@wNIUZh+dAtu>%I_ zyo?1g(~)1j*YQmAZS>B^$w~S)naiG{N!c>eIdxJ(NgizgJU`a~M2%;Pv{Jc@Eq?7$ zbBUovQT-FkVwofLVgMu;lpa|S5NNop>B(P7aY@L?mPURydLMj24I_V|eboQ9>or8e zElbq8?`9rl4CJ~Ty{Artr#xmDsToM51prUME~QSiQ|)e-n?FkCjxEbT)6iSnJu|XS zoFsyZbVF#y8Cl?I+-GXCwEon6;6XV8Mn2(rE*Dcz!jc5*lHKBwFcwEBS_TjR8T zRp!!<1uMgr9k)QLS)vp*w0!~QfTu%Tl&i~&zOknTCH9HzYM7sK|MJ98C;g1xv__l& zWR1SiEQq(MNTPOann6<%NjmV!0>Bp<4Cxw69&!xwDLlB|?^sUA;OqKg{4z*Y#T&BA zOlk60>NP^|kE>O+OK!zu4ePFQCzL28cu6Igu;cRrcLVbyuM{$d`1gOvvFDkv{Ii3e z#SKprfS{BQf*)$Hrp6;qDya1k+>e?!JnD$|YOtEtz!%^{0!R?1`sL7eY+K3T1j)7| z$)O{xf=CjD0ZR(h1)e6~LABlcOrrn_@he)^ZExIHIWKv?sjYwH8a!VE5!}Xred216 z)%$q>SC1~Lmr3jE(=k_Il|SFEAHjRk7aB>|49Loy2(uOe@+fk9&@j&xp=qml2K(dy z#Aj89Tg3npMH|(9ZC}DBocf2n_KZ_UpIU8ur5x=pC|Hs@3lQu@Zpvy+|GD z@WLQ(J5AF_10LHdi|C@;jwvlJKnB1*kOu(7?Q_r6@}wiU2A-fr)?@1vAzTkUGzv37 zH%q+2<(zZ_3@cGU3Z`Lc;#MSRiIz)*|3Ff*=ToBCuSDW+H0K|>r=NFV0TIBnS9JB) zUcLnHmgS>orY9{!m>!dgux@f~MmM_4>tLz&ZpK=wyu_zD2B7sWfddatUTu@eBY zBN44MP1Im;?8|L>^}~IIi@`U(T)NK?fZL@io;0n@KBja&7G(E4)2|;CxEEDx0KFt| z4j2Mla@C3uuS$U;W+lLn<)801R#NEN+-?ppP?jA3F}F8Acoz%b0(mHt_;KmsU$ zbi5BPz%SMFCXrJD<}Kb@Di0jo$hLmy{(w0hT!^+B77;7)zepYzjV>^)2KJ+gIszmN zMl(Elrel#zmH28+08bBeLBOa`-)=yYtu~mXt4jTZF=K?>4LMEY%xJ3w!13ymv@0m~ z=|Yd6)DgX9Euff0*yFSEy9$sFysaG!uP>?d$KPNJq)a60GHyPgnM~w_WOpWOpHv7~ z#xZdvfW60Rs4k1(!Gg(nB*>;pCrl@0fPx83b;n|bz7Tq)xuTrbXL=}9yrsghQAsm` z_){IZlhc*Z?N(cdJ@%##r@(|YXJi;a%?82>yI0>EVwkE-(vPP)BiNd%7M?S~i5WsB zAeqJi6I@hU3ummJ;3d=P0%)djmH;qu(!ZE&3B6va%60q<$l(2}g$Feyv>5uiH+Y^{ z1YA0^o5C=GLcEG>>a;<#DypS!GMb{!yA$%2`f_crgUx!FlC52=;!z4#7T&pGF8ah z`=>v~0H*7~r=;A4h#J1+xDudLSm@QQx6Fsd*8&2#y45(nu(|q z#C{1Nf1>HqGs4+72{mB1=wUVNsmw=m;@9Xj3Q*ao8_Haerq{$ z7x3)kaGlX#q*h6m(zcep{LG#cBdr0M@tZWWRS}v_t!hz+{t&NT!jR5l39$)g~l!G{4Bh zI|=X}#Y9YRiuWNLR2s6P03`7Q&m(A2>3r;CAmnJp7SIF1;pW)GGK{;7D^}M5bO+xA6m5wZrEZPxD`&a?6Gf{xm4NtSsz*G;+ z{EKg-1x}|3;8P;8?@Qoa^=cMjJcymgO;y6x@wp`e-;p!|mEWlaQV5tpKuN&mWs9ZxHQ{5>YRfA)kT}j20 zp>l_4aP(^cj%ArHj{Q~L@ir@yRMicl7Lnrtm%w?#DDwl^yIzt^o1MTtkj=%b1($H8 zSILk7w>|bR8Z9nbcg&Cm^g0p4>^ohcxZ|3co&jOI3~rqn!>E=a@-=s2lc;&_*o<6j z#?eOBjg1})Kia3QdSF1cd(eAGLOiC$_V=YzZod-C&2-_pc07>+Aj=rWY{JtES?g0d zw1AuqWdCGa1t8Z9bIL4pb%2Y3_&B}S%zNs3eh93_LFXY6g9IMbPvne-;2~ptUw_seW||Rd1}Ywm0gO?OeoiaxLYe%Q6Y=G)TV63}>G!Ew?2V&lwX;@vbN6K&JEO-QGQ)hc$yFKUQ_Yvq;~eluj(& zph7oZLyHsGXNWCfkWBS}iZ+t9rD0A0u9r4DLhgXi5E)d?=xlt!RkqyYIs}A3aYF!L zorlPjA$0wrI}zi=oy`#dH{jPKo2FQ4@fYAu%`yP8$x+B&IUuh=HWc)+;)FqtYygt! z>-T}7L^m2DE+e2YyQ*5LAe&xQOAHjlA6D)D5Y;hrdjL0oUR~jq*zlAwKx8 zfE*h97KeXClM_dJjl=j$30)Hak&V^q>2~3Yj)%^k`tAc<25)+ODqAzlTe5B)kjs&1 zdv9v7njmBdtDHTjz8JB}BIszKXJs;CyEVhUfnbGgK8uI#ct?&*j;%rgF#Dz7ro|EC zXynw`gBcDM)(TffpA|8}Acv+U>97nzrKQUMxmJVaD);BpTVR70@fr?k^E&-(*;{`Z z?$d#uoa}jEI}*E>jsTwmi0hMxy-RpE0Bjl+(d3zA7*(Zc6p#Y9t9Wh|+oe(6ZzpA@ z6mi_vpZZ4!qnpljShoq?(Z4ohXylF9Y8Zu9AgF0R+1M06&0XZ{>Ys4@v>@2*Q!5Gys*#a-U8T<6M~?hh;D2^4>N{YKwb)Pa(nRC z3_~adS1gJ70M(S7g@$Bh32Gskzj{XM7Oo-5Lja1bc5ea9$Gwqz^ZWea=%Bc6k1Pve zwhT@p)|Z7d0YjALW8s%;M!Q<`=ZZm&!liN49ZN%}atjH-uK+U*EV8lQsLmr=Y_O>r z9qJvN_J^dT;xakau+u@i7HmbS0f61)N6vl(ynR9m(4*QV;EYnz8 zLe1afu_hfJxoa%iZ?*3%z6+DH!tQZZ3UG|h|0M|e2n#lWwBjLN!UCOoUG{|F56y{5HN#7`kFI9{P*-AAO@c{Yn7`;^=q4@8_9Hx z9;t%1y>$=~=m7zC0IOg$sfitZO6nsO==zHaVk_KeLzID_J4G%faZ zjOY_!DpsL8Z02>N&GS#O5|Wkp{@9%)J!iAlfbl>b@BWY_{3=s;*l`4D4Di=+OI@*S(fnopXE-9(`GsdFI%j)2Wm05BhShT|v!NZ`0L#ja@Z(+2Qc0k0)c+J~^D z5G9ST*pIeeK#Yxo$5xLz(Wn(y2av%odjRAQqt!OOh9K*kvC>UYbaD#N-X^ z0x@ung1uFb)kz`%ZZS!}gz%%9E)L2*HQkFYL5H;#?(c*^0G9x>beDuKJbmzEU}#b# zAi6FPJ9{9AT#aifm&K}f1l|dFWA;R7O*k^rHgDH(_ zN8Wb7e-wPVoLO&USdHhfCn+#U)@${gI>5!7 z^b(I3G#0-bak_^cTs~dH6))s99~lBbbWI;}%GU26Zps>sXHgHz<-_99;R zrvYjC1>G2IgB;4JdHCe|XhgQ=9W@15K*AuRHbZ==(hZHeqHv0)C1Yq@CFJ6okdOp` zV}qe0grEv{o%4dP!7h|eYz94>h72Or-2IfD{_YhRfP#X!7`{%T=Yn=QFj^Fou#k~8 zhpN!aug|m^ii#_?;msHCiKhJS-4Le`w2jehp9Y_Hok798+oecXzu?py0ocAwl!nneUo>pC;eb5P+=qu0@Xv_G%yf zGEe|IAWUeG7NfS%A2N{_efhvwS&|83GZ3KLlgXorc{(|G`YL^5qyVQxqyV<#^S7zn zONJ&E-4Gz1Re`=4Fa(inpr8QLf5AIoUk)ap#9|?(O#!;+%a)8c^}s|j|3pD zR6(yPwtBS_N`sgV?&$-%i7HKy4f`$PmjR(y+;L@S;T=He4EhHqh^Q!@hJakPfj7E> zr%==8Kt6S1AER)PL>&UiyeDI-hboYF=|a>+1fipF3jpE_VZ;p`0&Hi+)N2gF;pnjd z+gLIQDe;j+>s^W)14UrCoKORLdtT zdzuKgx&;sm4e(wK0iC>7J8ZbbW6m&}262yMkx~+&x&$B{i}WXT@InW^;V zO7}gUGXOBA866&UH?1(eV>j28SPHw(uwUH*bxwG{DKJD*9Qpby<}98pxoo`N9((leSAt&@p@V6=dGzkd_g z843pDf$eU~E=2u&9w7}`X+ZN3muJ7`#?)z;a-SW?gh@I`un;vO9pgqM+Z+QDI3?E! zod{YR0t5nfDCI}M!M_dKn8l}YNJO03E45%aN9j8`%Kx+ z`D0#%-v)$U%mVblq%eKaT%eHHN7j)vq2nlG^uiRq=Wm9X`i6iOw?)TJ1h?tXvV3az%vU zer*29fB;xvrbkaE^dX_a?Lac+9zh(k!5KmWwo?F+kntP{1TJyoKSD@H_Q_`4Z(KsW z2``ji6T^3jhTR>*E-?T%K?1|2UBVz5E};P83=YI$e-|W95Zb!2$?C?jq>n;~2dZZa zd}oPjRtzR8b9L;Rmdck`zBB<|`67v_H_sdZ0^LmfDa>*raS6ejg92oHMgszfaVcEy zt`@`qIs#pZ94boeEeePwC1MN0bv+<}4L;ag$Ri!i*6@J@*!4^fz-B^|fCxy4oudZ5 zqX7Znl?i+I14v_-r$7uDuzTK;+bY*y{SFXu2CohZKvp+B@kp6`ya_ibh{B$BgA|Qp zsaVijxT7!`5TH8WGhzq@Te$|SKoRYq zvQWTmrZp8IF!y!T_|>pqfKt+8xS(tfHymWKPlT~cD;&FPHL+vG3Q#4s92lMuvbz7-2#c>P1$KKOA} z`&se*Xfzb-OcS872VD&u$&^76fd*s0FNQ6n0)6tP!bLNifn=Hho+jC<>}F0=7yPAQ z>#2=0NYGcG)uo9yaJJ7WH6E^1-0mL{`yKyVIj!J@8YCoc38XFdOb|BO@MZKW0x&0( zqigQ#o26WdRh5swmM{mLc};P*gVWPVw*v!aSyVN{ZD(X z@wmV`C*;Njh~(=U0!7KuN&-aa+E05C@N3KMH&PWCyFfM=uPjd?F4W?m} z=9|4cBC1x34pEduk5>_ZjEBn9UM=?NYNHJ@);q*Xi8VxyZC3zbCkfySDx&VAKmgJD z>ie)4g!~cb&A2YwTSW;23i8kDv9g&Hq5oVrmemT_0KLBtYzVPTgQ;M(N~)XOM*(M4 z#PxysamarR#UUGX|7ljy0lWGA+GpQ!1~#HbG_X{;4Zw9w5LcZinJ&QQ zZ-FAfI5uCXb}7a6TGmR>Sz%xe60XDaA_U5>PZl7Qvy>mH{kR4|cbz*}T!mC9{zWQ? z!nj-_Dq1yQ(?$WFelbzw#Ty1o9bI*djrLI49SzYj0C4~a!0O%#AwhzR53H3v?|(s8 zS-l}7fWWP4o-V*bzvmvsp=aXGGlyu~g9GOEdxfwXR02to z+(`+EV>0`92s_d_ITeXzcN;bkpFd>DOd}E?f`=Xh*j@q7qRJ;g9)6jWPPRkd03J$a zS=ZWV<}-lk5#WKY9jF1oJrPopX_j2eYWRD)m4OK%Il9YzMj`}G0fW^blQjamNgL&E zo~e1pDAzG}(}4@l6)C3x2zN9byWa6PflG*&8kzwZP#|+>X?Cgrzprhij;T{%=*Ip$ zT>lJ20ABJC{sOl77#4tqrmoJ(NH1P2Q(-UngW3BAcXXsgg$~1J8+IBLoX)?mw@W7aHBwmKwNij zvl!kn;{Hpz7q4F=JH2YX?+qmuzy5_sWm*3m7~h}j5@(_t$Xx;?gqT za(=#iQDEa07ah%7032j^34x*j1+WbkaY`SzQm0E8ZZ6h;A2K6sppLF1qu0Ukhlp94>`&vZdidL0XQgDj^NqKx`Rf zpbJFK0}UBB?nEgE-k~4@NSD))!)KADNt}$ey6b9eT4N~wX)x-HMcXz7t{sR{Ix+UJ85Xy0pN&heF@PRT zQXSDrQSId@1E+$_d6mT6awjAXQRk+~)9Xd)Q_q)5ZFNWuJ^uLDSI?CCmAW=~qtPEJ zG8lS5dwP~R0{o#S>9^T-_bC7iB_+VO!O64}8iKCoje*1h937PcY$4XCUniL0H4l_q ze6MCI(ejb=5V;&6Uecc5EVOfnWAzsPhTD5ZDI zU2juTe7XPPLE|yg&!-KeEovxaX=ik23gxDXRkD-i;7^^IYy^+h-HzbTDI@?Ji0*R! zqZbW8u8dXR`vW@=0t6f@mPB0j86&|MQr71$Uog;fVQu=->4_3Ohjb*IU3@1*Ov0~5 zruS+hnZ`oT*g%&*@(7pf@#`!#4jI=qI}r8e6@DH7&TvS)m>ThL#cJnuSw7PBhVgKA zBgw#Ab|(D(Pr!aS9B6IbnW_F3G8*@FU-xf3{8zvygK{K(N=GdDeoY_2KyVYo3G1l@ z;Iz7>yr;VF%PcgTpxkZ2*$H6iBkXe5aV5yYAB~Dr1;7=j7}}&?#uA&+Q#G5FAqhk* z4i5KUmF01f21HCh2KJY#^s{k&0HB$Mp(I3tr$1}7TrPkdac|f3zr?F7mK|uh8;UxC zyN_VB8#(2`Yl`J_d&Zmep%@}Kh;Q;z0G=5no~DOqz-fEKcz{)0(}!k=KPRu{o?qG^ zwyNKAR4a*wLO21!-M9g^@g$`o*dzH6Es8UmoYY@UGlkn`qg-Nr-oY_i*3|0iG}nVW zp#R0ve5zIAU$|@v5JHFqd|9n6%|2_KO%6?Fp#8>6FBs%`-$Bd)kbw#c38diZFaGm% z9x;LiFighQub{fAlqvzCQ}hK$m;pXo!*0wV*=+zoG5J*BYaoRHY~2!vF)Rw8I=kMG zQ6rCNu^>+Y?jf0qtxnU>>j11J1>6Gj#}DB{NFW7N!i~=uIs_Er!;|j_e%hL3?O9lh zSOiCb+57iDCm}e44ET@J)Y?)byiYGP16a7FE1dSlU+M!AWObL-PC~?-A&!6o@TT7r zt@ueGA?Og}+v;Z%a2ai1jUKqISRD<79h1UGOd_bNC7;_)<7T-oK34;Ov*@$@+1EW9rf7Qp0@F*C3Vj~-?SAcbGz7i8t4 zCYQjuw&OQQlbT~a%Pt|9X*hqp=5xsO0- zXO9Xkn3{icnKXEC5&9e)Em(N=L4-w={)YKzu{Vpw`~&b665Y0(*(H zfCL{925fk}(7?H-PC($+Oyva|QrrWGWc-C5Lszb|@M3`YK;I1;;_Uz<4%HeP#0YL7|JOl$gu-0spkG`0o1iDpJ zDHJ1b*qu<74K!XBJ0dpehZ z=1PP0v0sQMK5FxbmAGh%V!@mLe*wvJ3qY=zgu%fuf;-R12m$sGK*)d4PbIbh5I%T} zvU)nkohABZ=jn|LANH2+_$dInj#-g=)2B!dCT30$c*xG4+8!%QzhYI6+DG~*ppb6; zfdPQ`^|pE8+O|tGHAi_(Nt6O+FZwhnUX}<0h(Z|FuzIXbvz}$O6{6!ffCc8yg5(pY zt|i%5*Pw>A=@N$>CUZ^=4}5?;k=4c+)Wc;E)!PooI0#9}sAL*TQEFrUD6s!CfFuaP zi*K#MB4Ta^H~Z$g(G^e33Th~jkYP1{vQ!mWQ>t6m;An8kF>6)bM~vd?txN<&9tZ=R zNYH>yfWyO}W6GCOBW<>YqMM{IS9iZw<^TVdc0RwcBzFP-baltwB;IjL2(1r;-O2s| z7$lU*#(A$2MFep{+yj^;7jBb?gI9WaTYhW67j{Rva3cmG!2yXC;t&q()_Yhmx0o9T zLfXzmyc20ptfcJwOGJ?ovy-*1bLd!3CG(f6q^1$DjxFYsU@G z>IPE=0FXRm(6*fTIe`DMHI-gwr=3qusipM(9|dq*6|$EGv?YNuEx!(mEGEI%TnWI_ z%QbbVS<9K{sUoRPsg7yQjlxR-vRM*2K2?v&Wp>ZWX;GnHt73sm<4po}Z3>}qO}5S-xO5CN3Z$m(F8 z!kzxBl$NAR?e(8@;Ti;=?BbQ~_rOn|{1=RV@Qglf$;Sz>&*KiB+g*b9EkK|Ob6Rhq zrUCrn04B7j_yu_nl#%Rk^9wgIqZctL=KyH8rqowl(t!m)pcKG?t)|0wfORrBH5T_X z$_!ux{XiCK(q5@h-UII=0X#3FM+-7ol$Bnxhs9kyek-b!>~<&+R4or*$wOW8iqu<4 zp!{R*q@*JUpI)Q&Rk}G)O$rHks{;dp5nGVh9zid#B%@i6dc-6cSADuC%=nthpis0# zmJvw2)Oq^@B3Gz++~K`IvRw$rCsRN;v}o%m@Jv=*$H3 zi@DoL^%d4K-nXhoL<$h$E0w@Z(S@_5P-GGSeo(VjTU2D`wa-*E){D}7L`Yvk-xp-{}09}pUVQ@$uE6dfrE zSTgyeT=NQnYVgjUaSAB7?+FQfNdvO?vQ%^?X9+929F*W|Hes}{NB|y#^wYn+ATc|% z6*&)ct7_TP04!KA+blUUyKfRMP{afEZDiglTO0FzrEwv5^7yyZkgx}MnuS<}q9Y{t zMG*i9+A@=WVom^=sRZ!3rzz|G5)^>A7YZof3xOQ6pZ*q|G4mC^2M}=G7_~pZ5P*>w z0sJL;a<>Z!UFk6Z26kpDLIX*w+71xF@YGM;GS&yW5%3C~05KmlcRt<$l(J9)AWZQf zn5poG-;M!tTGR7V@Ridh?y0h*0l81(Ab>~kVN(8?=8T&pgA_8_GT8MmfqhV#_?PAW>hX`*%<}|5;5qqp zA2@(1Z3(n7Fn`Si;utcxz@vd%F9kvNFDeGEcuj7R04fcSQvguS>kx#=!_5L7r;G+j zI*`r_WnNGp69OclNhJ-uH~?YUHGo2CQaGe7lQBM10L?Iyo&s)QFoq)pHKqmk6fzktZqJa-!k)rH5e>G}KDNWsERN*Uxw^AtIzJ zr2+*{c_v`TS1^XRX=K8&Fd^p1^0iCaGvVZaHGt>qm6v|d)~_;YIsowU&db0b#&Dei zz&$g`iFGgjMiyvs2LR=lWDx^9KtVTt4X%Ovl!Sdq7Ys3Xfo#SXCd#G{M8Je@l)L{J z^Oz5^d;yD`7yzy`O_T`&Ab|y2v*1u6Z{g@+&K$BbfvjW3*L>^ofGsFWN(BMAAdc7t zT79XTM3_jM32-OrN+~lYQ~xOd!96D+{BHr0Jw*c(!Ry1+(usYR0Fo8lu4nc z7emVPg{LM={c{Od9bfK5ye<(?{>|J>evYBP=?seE_aK4LTvu5rx)YwJ!SYx4D|K}K zdmAJ$B8F0p;j?EwwnmqdBLM#?RZfG3DVUnDacgdg3gtsNlK^Nd*%1_{>j!Y_o_6$z zZRnRF1mCr0f9`fN1)C*6`0kKWY+J)_n!z&)71y=Aiwy(tQ;1MddV49`kxT%EMWKAf z2>{3|JgNw7yH)rKj^Kf9@YN*{YikwtP4-zyq^5!}mh;2+&Z58+BX(vFCJL7m!Y6BA zCi>d008e11!P9KZkp^bx*a&!(nipKj=0$i42uKr-w{PZSqA@6<#4>XGR1lKbYQvr> zxG`5$btC83m8(Os_k*fkS_1mOo`&a&m(K069eI)|_g*jXrYjRu9>aMhLjVGNAWncY znNmo0jsQHm^0R$_Aw*c*`?8fDfH^EU2KFNYwxJ-bo;|f_XO0W-fg{O^Yr5g}s=rg# z9oOSJiUMwcNn*JKfw={<13S#CkImd}{|JC#{S?R^OZ=RZ?vZlDOLAZ??W;f`Z|e~~ z=Shj)GFNB($-huoBsGP2@$UM1oBRskl5Lq$C1WGPDBme$Kp)2FJxxLvzWB|#rvU=X zxtYKl)t5jL3t{Djze582h?kP*M+w~sKmcI+kcXB&i7|Y2-4u8SOF=TEJMvQ!;K4nK z?rGDU2z$SI0PJb+1GZp*uJiL#HX@7{`ZNaMOGBXdJfR!oghCBq*Se9{S1Gy9amm-3 z<0Qk=Tmc-hm(htRW=UdOl4p3qM$;y+xI-iW<6SG0M}#)=3Ix zlFP%yw!*{T1!RYY*+E-NUTsAKfL^*%eUE_CC*Y@UPY`zGAvWYkLfSKi6pJ*mVxrj1 zd2qDpe#1V%fm@s0Ya_Yu1AUk#u5Oyw*?@=@!dLWJF*H#Qai^e&U#*i0;|nvFwZau{ zN?qBKn$em-;*wb14`sYz8wl7j({KornrzyXCidMPsSxr?9mHkauUYS+P?e_Btx`1e z^Awu^U~FQ&9+Sw|7?wYXTA$@M2L`mKSh!1wzLV^5W5Yq3&mag^1NaWFkW7H!qL1fm zIxz|ILOPo!0Vc-AbEFnfJp&p6GsR%328$RXO}iN9#tIz!3sSBII!2CM{Be(2vZnN0DN|=Fr|b5GlKct zy2dNF9##T75fTm+%~W?y6grD=S}3968pMMDVDw;B4hp6~Z2o}-H{XCW;Djy|3J(D7 zbcA?TaZKr1nyE;vDM(j~cXSgBTVD-m2BfZ$N>XhBEt?z?`gqF^aQWH++V9v+ZfMe@H3LY1ate4qvO?+`S~HW>kti&#$f8XW zh*`2{`>~<+=CmYAsiWV%8^u>3dNJUCgIAm;v|*-!7?(o2&mi9cTn9kdE>Cz>9ufeB z+J&4BMAVVu>6*5&or(lJV+Y~VZD^$oy1g|sU$S2@>Yl2bf)JGLlHJ(ab(FSq$$9|V z{Jct^!(vk%gTU8D+FwwdG6lF(r%TJBX>gPqJ;({{uf60pN$Kqc{#AU`5ci;YDId@bwh{p&|&ZDYl;m!frb6GeQCMR#rRbFl{~ttoSxhaOo4g zrCdP|;NDg_o~{aq5IpS$B=J)k>A4xoexXRB*fxuMiU6;u-36p?s%iz%KXf_%?VDwQ z!vJDy6`jBdU#Z)+Lc7Zq;RXT`H)pg#*qdAsOzb5;2jY6Q6&zvXzpE&v9grOU!6!7M z3MwrA+^iAEBMdvndk_H0ZB3_lb_`_g+@d=sO<}}5Fb(Jn%QY0Z@PZ|G&v-@oHVt^o zkpID{Mw?)>@X@A=)u;mz(|~$0rUkdIPP*FIf2R~nuMlDDZYuZYWSs5M$j+zhN|x-kFXlX>|^uKn;jBK1qpaBmf2f2lUJk+eT;OKkx(Bkz*pDS6D^gIvWEF`9W?ud^N#|42|Q}pH6NyR33Cww zz`rW$C_kk*5Y0hR^c$?!=5$ai-X znOi+1NSFaYgsRm8J)^$*5|q&)_2(*ctik0Apbigr7!~+!oUrVUfMar0j($j zcB@lRd^M+h|KITgfC!kq`y_$&wM9k3?6+(7LBLwaG1}RgvpC5yE2LM;4Vl9gq zca558Qk$blp@(`2J}VZHU1%UahB2^k4zp!!%_pCi4B5=}rjE?}8HKWsHXJZr`3vHT zSA5KRnyO<3a?|2iaHmGnxJiM8gGycTmF;3OaGG};1yI(;DS%qUQ;0Ki4F0(lABo}G zAYYnk*qWuAkU-)d(doe=a(98RHi$iABa3y%osT9AdY`itRUgBSI{@T*<#v{^iN&1e z9=#Ci(j{V48;p;;OWNS8sdQ1szrTrzEFf}C39(pc#Og#P=IKD>yQc-FntHQnWTlI90J>Fh5-4C$Qi(t zJ$E_W_W+QE;+{I*@v4f@JaYPZRVbL2x7#?n9g@B4h(3YIFRLij|RgWSn`G8he zaKT4$sT!F*s|RpVK%^}oGWK+ptqTp+TC@Ve7w=bKJy4UdGoeX!mr`u=$DBJ~zTez? zfA{--_a2Ip%Y=eC0ss((tqffQz-3G>5X=+ecI}J@u-qON8Wf%Uc5idgpKN8~1C6!( z<$v2Q@6NQQZG)2(!Hq|5^`vY&8u8(mGpYl=U20RPb!Nen{wPno-f#kb-&!O_L0j6> z1qWKMiQ#bVaR~OF#?{%hjU>l2NZ@GKtd@fNzxqWBnAOHcO8VNH*8GVn$vzM z0|B{tHvzfU4n}UsGotLN;%S@&s@#u@zA7?N%&^8X1T2+PHdu$MW(SDwn+${o_?kNH zkJGaZ;lx#7OR2tVhm()rnOapRF1XQ+ zks|qlagP)4`~S)<=Wexsz7lLvPy<7>i*!n-%;bko_z77MJQ*pIS7`ij8BcDk6+R%K zkFLNbrq1LUl5T#zvv18O94ffm7O0Yk zApx$yJO-9w{+hFmm8*ER45|KY`@!Y-2RAEd&iZpDE<0+vWV;d~hI#HYRRQI}LzQmDBeDfuj`=~9(;xmU_; ztK1W}W_MRKJaj9rDN63xeYuLO!B*duyoC=q|4@$yl|%tH;E+F*)z~j_^dp6PmY$Wb z{PGX7a|iqh0Ysk6%h5gU6qUVsm2kmEY`V7bM)n!Po<{U{YafY_{PD%(w~yri(DI%& zTovsP9Lcnkwfa+_o<8>OcOMV7*X{h{zz4O&h@@h4@5$2M!N@+XYwfqkoYPbO$%kgw zhCqF>AB^a*1e$?GL z>%0a-lub}LmZ`h3S&ZDPHI{ux15)RYIumqg-w~zWu!?8TYZ;k^&M%K{zxuQZ5Q$|Y`hK_n?6M_m+5&6sBtF+Nj|KF{lO=w7eewHZTk<0d z?_A%}weNZ@!5b1H3CM|oy+{aM4{q3Zr9W$1VvDS)>&-<3U2hFV-h!|cjdHmD8F}`1 z9~a)&p2tz)aAKOT=d7eFultfU5sV+Hf6?IP-;CAlWS;Qr8)p7$NDJlT?D=!~h|G93K%&=hZzPc4 zozvKRV{gbQ{aObsclMG?!;hTWG9;gEBnmfn)`cTb2M8B3dQM-lCc&dez}_Xqm{BmU zbEREQMzv@9!(A9QKO`S%)n--aX=KEPdq(?=QE8`0th!tC4SIl(! z5_I2hXltf+NR|6!lL0cR&S5sAh?A5Qf>7-+dMeO zKfYf`5b)v6)cl9okI!w+ZGH)H;J7^i0CBH*>NQVh24GdZzwwM;!k3}Fl-Hs4XG`Rp z3?YsJyZUR($}1|6{;wc(jRSOX06Z1A$ANw8i!b^2CbLk&IuDq71BSxWFuZ#Okm)iR zv=~w6_TrJy1Aue;y)TA7Ac#xS?DNh3ZlaA$Aqs|mwD_GMNZo^5m|faV8#ReloD*7F zVxRp{aliwRF9rbVKpgwcEa=bCDv_}SnE=4{$LILt^U6u3IOnA=(MpPEpN~jsDPmwWerq7>xb$a(6-I}W;hKb zYFYD37+wUsh6+;S(y(cQGHsPniuazhc?H>LzyS|H*#bbE>Y4yDg-2%M`7r_{)CK#R z3N}QC^lK0t%yb(C!7BphxzQ;yIM(A%oc_p_?Qmg=w{u#HS9to;J^&7Q0LX#>z!qC{ z13=pVI02Z3o`Y}+H$f4$<7mw(AV3IVcw}EI4_G8q%9@e+UIB591H@Co6TX7CM3T#G z)IzPAW{}ho%YlA?>y48Q^ZUvLIsnOYNJh{+02pvyJNW2-!MH66-V|x#JDhZ&wb0Kc z76B-YI0}ubqfnpYY277WG@BqXE0SHB*HG>{$w#YJZ1rjnbA}Y51!wecc zAerR3eV@0yW+$qhQ{*+}jrN!}JO87)Jw3Nk{y0HqD80!xvOP$v|2{L6={I$^_T zu+5s@nh{-41IIChClgWE3zhI8^DFeTS%k(;kQ1|FcAmS6b#0ISaII=LQH{lar8iNnC{mt2ITmR6h(WXr>T;|E5azQsL zXX!lZJG_`D`_gg&vHegwNiyoK-eHq8rMYGpp|WwE+dVkvpm5^4ah6|hJ+SeJmJo>< zRpRU{lguf2G%FY_IA*gTAq_vfexQs-hxw$l0049n4V0jC9AJ^4GfJ-bSq1@WpSaM( zcnB;39{^A!H@)Cqe4Mxfy;%W$RwY%s3;vtv=vIU$6e5eYp2l}pntOqusJUTf~am$=2d9%(mqTOcZ7PEI)MT;yt0 z0f4IxJQ6wuAaxBu<{E(Sd`AbY6$v67#Sp>8_z1H@97% z1s;InjsO6f=tx)&ilz;vZ)VpSMu2P)2jE)}d|5N5gsRk`#orY^(&;z5x}|{mY8=O@ ze8sXKm!BC4eI}L)0BFy*kWHttmYcW$Cr1c$kwgcHk1&JSy|?D^=IXJ7OaYuXQICW^ zQR+AVl0^UjTVU%ycmgF?XWJ4XBUhw46z^~6HM~@mW3tFANS~1kJOCg=LsRs?tPpcL z>}^x+^mN_&@V(W$KJSrwEbfn?k%CJ_s$AJ$7fX~{^O@6!)A+!97=`9DJVKLSHdoQ1)S}TuaP-SJO z%{N*$WY(irbsyOfO`p;|4){c=kh>o6vk*KFD~{nnBCNWRMkY9}Ku=9aDy|1B)=dR@ zFEx2}L-I_ci;OP>(S#fl-USEJ2S!2~6=13@|AtMd*4n?o9H1lw7&M5F_^X zG~JSg%8b$vR8q=u^QC4n$j}i-c4JZB3qmM@ZCpvgt#OD@U=-(6zriBOyB_TQOD}j( zd0t=#zynaxDVg^w%bz*_7={xCfNvLMlXxK{OjieMbaUk8SINx_=0r4d{dVJXPgC2@ zS9m0M0055wpzL2p=K)fZv4j>N<0!e1Hc22j{snk316WS zV{%T_OORs>S&YvqT#i%KR<2V-;!li(9sm%oOE4H-V)as&TBv0>o?NXWg5GF^2={aq z9=%6pxEKJj%}?-m3G=8;yMPTiI|P7L4y;EGRbhlh{0egIEA5gr$2=t4^;dHg-TsSf zB>d|na>diJ_~Ld2P!^>7YSxGuhr`WXzPZWYaj4LQ$%sWAgrE>y}%_X^e1cn_LrI%BF>XrX)=sUi(o z`anXTHC^!Yp9vX4U@7VKZVz$=Mg*B6;Q-LYm>|Y7EfM!t0-)mf8TGE$z($pLNQBEr zmkT@q$Ta}0v!)8TH{osoLQYrfTv8D0J#ZP?qP||3_{bNoWd{CrFC5^%g`6Q_e%~M$ zHa2`6FXpIH-WdQ5y=YGyxZ2`T&5zPr`rZ%y)9kJQtkj=Nl6=fG z?3Nl;@VQ6tJ=`U@tdrIAvE{Z&l*)uw2WRD*+9MendH>Y$D&WpqCUMhL2i-@}n9qC?Y!I!GeFC;*r(ldm}G%koe_ri*6f&EbPK{5==PhHdyrGKDnL zZU9&$el7gei(q;RM)9nR5?AHSTx$84S{77952t;$a z^oc+}kca!)o2W8AAKqH|Jp(mQAzkto*@V4NBy-e#G%PIu5XY`u%rz2L58z9d%?<$k zl@G6A4}l*YE*01k&MTK|d?{`jBN@wYSEXRi%y$eL)tr;18}(4QAtoOiy%ELBB4H7C z`eEct0sv)PsUtGXy2+xLV8Q7IfTXY^bx*fMfCJgp_#P0OkX_1Fe_f3R?TDcek>(GE z+sn9;zFJo@HbEC|?@j;WB=o!LE}@O-l2kxpflDW3_&3<_ez%GhO9GJJh%91o2vZn{ zg104?a5kBq-<~0aWb!~|{jmU$#enRDU-Ut{Xg29Mfe02(26QQj1$U_QiH!`>nNB2O z2UVxG|1`-LT!EDkN9BYJ!)6g;39mx&FcSA!N^E_%VJiUd#Q(L9atvjjLvQMYsL&!J zSvv zfhVaG9Ed-?sy2F-6;QVDt)LG60_Z9YI1^4&uLz}_9{`1!3(bQ}uK0uDmL*PY`(4&g z!&qdCT1=4lCnT-`Naq0{9zJc+by_Thue2*$Z!UV9h=t+T%t%4+!;dO-Qh7$;k4i z?z~^Y%%ruQY+m`^SOkGuSd2|5N4k8Rb?n3Acx3fdIN$+DCj(GSi>Js&Y@W2vL7{}Q zmG}3E3$gT!P`!=#iZF)u-^B!*~?>W6N+z)AH;Qx?Y1NK-a5+6j_MPnBAuOAEtJOHU{0I~%D zD0sr{6KT(|4T`WegW;N06O;mWjj10-VkGG)i{pm81vy@mt_J5&OGT3ekGl~W6R>B%XeREen~#8&Wq{5oz0lI~X- zbvuF){uu#4{#mKO0|4cOtj9yN2mq**%L#2V-EoqI*KuDYx6EB7>%;idz|nRyzk>49 zBVqB;Rv;f_J@0Pe&>u{C&WAZu=q84ic0p+n{3Jo52KBPFD0<*5!m~9s3y0m%AR? zzI#Z5mPA4lI^K$@LUVTqpo|`$9iviI#vLyR;ozKdn)m|e8nfyujxGPz5yc!sw-u;t zq2ca|iD@qdVbY67Sx&SAaR;hHy&yNpKF#d#rpu$%uxf1jN@m z4}bqb24?~avmM10#*TMtlM-Yd7tB1*8ZHr#SFy8N^Njh^b>Lh%O3p zm-hq!y^}*)004_;Y6VU1hSf)#Rq)>l__T-?4rzw~+R$?vzad2QUhr^XC~gzE2yvXX zJ9VA4J8`Wa_}Mi8f4H}I{Rtr?zIQ|v{SsI>psicB>+fASaL~Q$^MP2%hRf=#|EV}} z?Zgth){;dJpr&K4tN)`=S*@b4{uG%3I1x>^tG8DaYjdx2&FX(5BKJ{gZx6#ijlIA- zv5?tHNMz%Pj03Wi#EkZm*3le`yPk(bWX| zr$fTRIT9w00mzqJfppP`WUQ%!udbAGY_8nG(l8uJojdD!?eK<(G#t;9hBWJ2PKfju zOv*X;T|0DmIA!6FxDTND0kBgRs`NfGCF~b4QrfVyU(K)HG#p4tCmagN?M>1C56`p6`XPp2fSn1(d6~*vQsc$V(yvaJ5kz*Vv2c3SR`2i^6 z`=lemqYhcvw6A6J0+1yw&{Rh1oS-Q^YAWL+NrQcZ((^`*36tr z^1z3;Wo#zqe=_M_)Om7NBg^XL!_2DV!NniAnoqQR)^7bR&?Rx;4H0uWd0NZSA^-Cl zZjuET(+aRi41qjeVqqfHtpy?U!iRUu1!R<1kj-a3Cr_G(1eyl`Tb+2{Qf@~%f{+cV zB+dCAp+x-|A(R*_lT;m!dulzx-lt3`QC}E_V=*(|kXJw-5eGZ~aUabA?&jZ_(aN5w z$7h*700}!2f-|K8Jq0PaDS84o8CWc};XB6i>m#L588wHSbt{$O9tnN!`bhwE*GK4v zE^MLG1L={09@>$s$B?Gy;WyYnmg?|3XXT=^_?CZqD#$;Idq0{PkTrvriJc{|1%Vf= z7&KUu4Py*=i!c#tc*af}jt%l&GW#)z8ELnikfpPlwnmL6&6nD9Zwb(t7w-iXAy4aD&;=W&vpM4H$qR`UGzn1f(mf6s+stgW-WT zJU4II=%-2;l#0X4k*^@h2W>={5v!i?F13b{oeuGR90o`}F920k!b@ zD-z~y3y}!3;~=3xzQ)rTXEL16R8q2)OlL-nuI$5s(Euwe1h&Ma;rKpW{HNJ>!fGyn z@qMi2Xfyz1CU%(33xM7~&33$HV&R||P!&uYTFp8F!{w6lJJEAxopaBxKgl{}7>*|k zf?%K-P6o`mU1B@{$y{XM6%@GO26DjVbE@auJ}Bb(TO#X}GhXx;kX&`;DwUq@?EO&( zn>C-qsBKZh0k0sLfPLZP;eZDq8UbKxz>LU@3UQaO1zxL+vMD#b&TSIm0KLB0_GSA zQ9vA10h#EmN~ZyUgEVWKIGtQ}NN-GTxnP+mjoqU$ifrpY3O*)#VW1w98$4-l5RX4S zEm$<|@QOzn1hMV_{WQEFat%P}001e|-CrTa?};c9IHaAwTp!tyA0GxmDA0~VU0sfGpU2OI6)vd|JdRu*(4(@QV|P za3D5L{+nYeAl0G(bgOHBWs3sPO-erp>3smG1SG_;>Eb^G|2t6dA6IPcpZ+cgNEAwR z(e{#aYR3GpYH=^%XmR@rAZBAmzb=ad-5fA>&5WY^006i?OUb!G!f9oCHXFCml0g83 z@U<%bnMG1HVYm!B+7|MzY=x880lt7mwY-8~ypn3B=5yB<0|2^RC}kW3ZlU7*1IK=6PZF@ zj6qK;PlBfnzG>j)@>0%>1G~x@5<+AGG|vl)MFBuFg=gd5`|lC(Sn-tHi^JsuU29u2 z(hdL`Cvf10im>pRSllPW3AJrp!)^#JDX+|e40EZs`4#W7`=^8o@0$`zZ}dY`fd@d3 zA3+2J3aymThTlAfTGYwj>UK}9Nwe*K*2DsG3^!HmCN^e*2I>jfC&2*^z(jDeYQR?9 zT|j|KF7*UV8wOIn#8-cN7I7xCC0zySf04M}XT*VGAOMN;7070`M#BnqQOo{M9CNw*F%%g%^vIz zkGwdL3nocM;nQ)$l-vOTI@zx{8~jt^BWc*CZ=xa*%Yq3FwpD%1IzqgQuI2?>JXGqE zd{uT5Z#;4!_x0?_e+mu&XYv52;-{m6_+xX!1UBBKS|o1dg~@H|nDR~geb`%#=Ic_V zBl86Gzo$z@`)Z_0@08xg88J! z^x1co+;l^wT-s+`X1cojj8q#q6RWu)Y1dYd5F+wKHaFxCgaaM`55P+)Ic;%!AP5~t@OEUj zOm_hoPM|4CyiSDAj!J95BbiXrIPUFhf=9f9?778r4*+cS-}r}K>y8MXB6}76^$_RKpgM@cmQ@S;k<3_5?caQ)L!k!o?KO1JPrQGB!e&?_V2 z8C?S&2JoAzA-lU>^_yc2qO7aZrQEnFL2F= zBR)Z%VaHTJT{ELn!Bu>394I1-ejp4abufqx zuOW}k1t%6`H2Yq$622jGzVG-Zs%#;lG4AblGd-1L;yPt?`jJmW9ssJSgIV^D`j?~$ zTRa#`o`&_!_pt$#c+dl`zCtPBn-=SwN&r~Y!9}aKF6YB@?X1CCml@Cf3JS+K5SNYt zh^S-F>ToH^DDSDa{ug*E>DrZbzhbNzUszGwFyB(B$_S2T`fzq+oTfOh*;`j7yqZT} zDEOPrv=I@9u&~i#@-W`@9so6HTDlRR zVkl`_0opHUBm-v028a!n%C9{R_~dw)kBlbh#L(~(_0X{9Gkmc;cf4jn;=_TRAWM$m z6X9}-JUfd%91eH@CLd{{IRNM@+@*_^gXXdV7*0e%0_2X;FdPi^Aec0E6d0b}dbY9@ zgnN)M@R9$V|I{1~iMT|Lso>-|T`)@=qzhiYVNep^5Hk~YeMLs0%J5B-*xszcqC#L+ zod$xHO4i_TkhHaF7#0fHfR(B=G#|MYZw1sq4ya(2J0`>M19HP+b^sJw&qYo}I|@Ws zz@7{-l6>k=;iI@vi_A;yB*tuAlE!Cv#YzKKu$X_r*$yc3>n4LowuF12jeiB}(lrjO zKLiqn4gknI10E~D&?N#KlFoof3^a;+g#T}t;5CohQR_rF0#kTIYtVa6o6EO^k zRp#2AFa7kAQMNb$PF?{GwyZS;HwY57cksqI92melH_?yO_96gy4)Kq)dMi!!E7r;V znNmc00Bn&_Gyox6LVIMWWul~M*%JAL1rd(mKRj>+$k>%kbOUNepBe`|0O14x!Z`q> zkfx;{pjeCywg=6>up;2PGy8BJtj}G>z(W&$5g690cw!{<0N{B>V~4eDAVUPyh~f;% z=wi&mdN{pO0I0{T?TolN#n-a=q^V-lcG+vCuTyzyi+4Y^!=Q|oGe%iR(G2N@CpX-;Zz$ghf7w#>8gfBX)eYOkSNs^06tM_ ztc%@Cv?~%GTXF|MyC8(3j>?UiFuqfY2Wc+GhmU{*9sm!(ISt;DUWaeQH+4R|-I*Ar zh^Ymj8A_Du!FzE9SnpVhqR;TWkG}(2u;6myk?>*IanbGzL;8ep0YRi@Bn;I{m>MTd zmhFSF-s)af8?&N)_!qOOa+TjW5cs{+3Hdz|dI0cPH|BH+k4k$3FUX7!|6&~pNUk=p zp@3`4a8)ft>AOi6JRNhgC!qr741i^D017m8w=SayAh}t@+evXK_YU)^{8p^C{|6D| VBeH!{f^Yx;002ovPDHLkV1oUP1&06t literal 0 HcmV?d00001 diff --git a/tests/stb.dsp b/tests/stb.dsp index 68c1806..b5ce917 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # 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 /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "MAIN_TEST" /FR /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "GRID_TEST" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -86,6 +86,10 @@ LINK32=link.exe # Name "stb - Win32 Debug" # Begin Source File +SOURCE=.\grid_reachability.c +# End Source File +# Begin Source File + SOURCE=..\docs\other_libs.md # End Source File # Begin Source File diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index de25330..3f4148c 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -9,6 +9,7 @@ #define STB_RECT_PACK_IMPLEMENTATION #define STB_VOXEL_RENDER_IMPLEMENTATION #define STB_EASY_FONT_IMPLEMENTATION +#define STB_CONNECTED_COMPONENTS_IMPLEMENTATION #include "stb_easy_font.h" #include "stb_herringbone_wang_tile.h" @@ -21,6 +22,10 @@ #include "stb_image_resize.h" #include "stb_rect_pack.h" +#define STBCC_GRID_COUNT_X_LOG2 10 +#define STBCC_GRID_COUNT_Y_LOG2 10 +#include "stb_connected_components.h" + #define STBVOX_CONFIG_MODE 1 #include "stb_voxel_render.h" diff --git a/tests/test_cpp_compilation.cpp b/tests/test_cpp_compilation.cpp index 97bd2c2..4e77da5 100644 --- a/tests/test_cpp_compilation.cpp +++ b/tests/test_cpp_compilation.cpp @@ -8,6 +8,7 @@ #define STB_HERRINGBONE_WANG_TILE_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION #define STB_VOXEL_RENDER_IMPLEMENTATION +#define STB_CONNECTED_COMPONENTS_IMPLEMENTATION #define STBI_MALLOC my_malloc #define STBI_FREE my_free @@ -27,6 +28,10 @@ void my_free(void *) { } #include "stb_divide.h" #include "stb_herringbone_wang_tile.h" +#define STBCC_GRID_COUNT_X_LOG2 10 +#define STBCC_GRID_COUNT_Y_LOG2 10 +#include "stb_connected_components.h" + #define STBVOX_CONFIG_MODE 1 #include "stb_voxel_render.h" diff --git a/tests/test_truetype.c b/tests/test_truetype.c index 4b78152..d18d3b5 100644 --- a/tests/test_truetype.c +++ b/tests/test_truetype.c @@ -3,13 +3,13 @@ #include "stb_truetype.h" #include "stb_image_write.h" +#ifdef TT_TEST + #include char ttf_buffer[1<<25]; unsigned char output[512*100]; -#ifdef TT_TEST - void debug(void) { stbtt_fontinfo font; From 0214a3c71f33ea798921c425578ef5455c2d7fe8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 10:04:03 -0700 Subject: [PATCH 323/522] untested simple batching; document algorithm; automatically use sqrt(N) instead of 32 as cluster size --- stb_connected_components.h | 87 +++++++++++++++++++++++++++++++++++--- tests/stb.dsp | 4 ++ tests/test_c_compilation.c | 5 --- 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index 2ba78a3..c3b6886 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -24,18 +24,49 @@ // publish, and distribute this file as you see fit. // // +// CHANGELOG +// +// 0.92 (2016-04-16) Compute sqrt(N) cluster size by default +// 0.91 (2016-04-15) Initial release +// // TODO: -// - test C++ compile // - better API documentation -// - internals documentation (including algorithm) +// - more comments // - try re-integrating naive algorithm & compare performance -// - batching (keep data structure w/ dirty clusters) +// - more optimized batching (current approach still recomputes clumps many times) // - function for setting a grid of squares at once (just use batching) // - shrink data by storing only, say, 2X max exits // (instead of max exits per clump), and repack cluster // if it runs out (possibly by just rebuilding from scratch, // could even use dirty-cluster data structure) // should reduce 1Kx1K from ~66MB to ~8MB +// +// ALGORITHM +// +// The NxN grid map is split into sqrt(N) x sqrt(N) blocks called +// "clusters". Each cluster independently computes a set of connected +// components within that cluster (ignoring all connectivity out of +// that cluster) using a union-find disjoint set forest. This produces a bunch +// of locally connected components called "clumps". Each clump is (a) connected +// within its cluster, (b) does not directly connect to any other clumps in the +// cluster (though it may connect to them by paths that lead outside the cluster, +// but those are ignored at this step), and (c) maintains an adjacency list of +// all clumps in adjacent clusters that it _is_ connected to. Then a second +// union-find disjoint set forest is used to compute connected clumps +// globally, across the whole map. Reachability is then computed by +// finding which clump each input point belongs to, and checking whether +// those clumps are in the same "global" connected component. +// +// The above data structure can be updated efficiently; on a change +// of a single grid square on the map, only one cluster changes its +// purely-local state, so only one cluster needs its clumps fully +// recomputed. Clumps in adjacent clusters need their adjacency lists +// updated: first to remove all references to the old clumps in the +// rebuilt cluster, then to add new references to the new clumps. Both +// of these operations can use the existing "find which clump each input +// point belongs to" query to compute that adjacency information rapidly. +// In one 1024x1024 test on a specific machine, a one-tile update was +// about 250 times faster than a full disjoint-set-forest on the full map. #ifndef INCLUDE_STB_CONNECTED_COMPONENTS_H #define INCLUDE_STB_CONNECTED_COMPONENTS_H @@ -79,12 +110,18 @@ extern int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x // bonus functions // +// wrap multiple stbcc_update_grid calls in these function to compute +// multiple updates more efficiently; cannot make queries inside batch +extern void stbcc_update_batch_begin(stbcc_grid *g); +extern void stbcc_update_batch_end(stbcc_grid *g); + // query the grid data structure for whether a given square is open or not extern int stbcc_query_grid_open(stbcc_grid *g, int x, int y); // get a unique id for the connected component this is in; it's not necessarily // small, you'll need a hash table or something to remap it (or just use extern unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y); +#define STBCC_NULL_UNIQUE_ID 0xffffffff // returned for closed map squares #ifdef __cplusplus } @@ -104,11 +141,19 @@ extern unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y); #define STBCC__MAP_STRIDE (1 << (STBCC_GRID_COUNT_X_LOG2-3)) #ifndef STBCC_CLUSTER_SIZE_X_LOG2 -#define STBCC_CLUSTER_SIZE_X_LOG2 5 + #define STBCC_CLUSTER_SIZE_X_LOG2 (STBCC_GRID_COUNT_X_LOG2/2) // log2(sqrt(2^N)) = 1/2 * log2(2^N)) = 1/2 * N + #if STBCC_CLUSTER_SIZE_X_LOG2 > 6 + #undef STBCC_CLUSTER_SIZE_X_LOG2 + #define STBCC_CLUSTER_SIZE_X_LOG2 6 + #endif #endif #ifndef STBCC_CLUSTER_SIZE_Y_LOG2 -#define STBCC_CLUSTER_SIZE_Y_LOG2 5 + #define STBCC_CLUSTER_SIZE_Y_LOG2 (STBCC_GRID_COUNT_Y_LOG2/2) + #if STBCC_CLUSTER_SIZE_Y_LOG2 > 6 + #undef STBCC_CLUSTER_SIZE_Y_LOG2 + #define STBCC_CLUSTER_SIZE_Y_LOG2 6 + #endif #endif #define STBCC__CLUSTER_SIZE_X (1 << STBCC_CLUSTER_SIZE_X_LOG2) @@ -182,6 +227,8 @@ typedef struct struct st_stbcc_grid { int w,h,cw,ch; + int in_batched_update; + //unsigned char cluster_dirty[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // could bitpack, but: 1K x 1K => 1KB unsigned char map[STBCC__GRID_COUNT_Y][STBCC__MAP_STRIDE]; // 1K x 1K => 1K x 128 => 128KB stbcc__clumpid clump_for_node[STBCC__GRID_COUNT_Y][STBCC__GRID_COUNT_X]; // 1K x 1K x 2 = 2MB stbcc__cluster cluster[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // 1K x 1K x 0.5 x 64 x 2 = 64MB @@ -196,6 +243,7 @@ int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x2, int int cy1 = STBCC__CLUSTER_Y_FOR_COORD_Y(y1); int cx2 = STBCC__CLUSTER_X_FOR_COORD_X(x2); int cy2 = STBCC__CLUSTER_Y_FOR_COORD_Y(y2); + assert(!g->in_batched_update); if (c1 == STBCC__NULL_CLUMPID || c2 == STBCC__NULL_CLUMPID) return 0; label1 = g->cluster[cy1][cx1].clump[c1].global_label; @@ -215,6 +263,8 @@ unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y) stbcc__clumpid c = g->clump_for_node[y][x]; int cx = STBCC__CLUSTER_X_FOR_COORD_X(x); int cy = STBCC__CLUSTER_Y_FOR_COORD_Y(y); + assert(!g->in_batched_update); + if (c == STBCC__NULL_CLUMPID) return STBCC_NULL_UNIQUE_ID; return g->cluster[cy][cx].clump[c].global_label.c; } @@ -355,7 +405,25 @@ void stbcc_update_grid(stbcc_grid *g, int x, int y, int solid) stbcc__add_connections_to_adjacent_cluster(g, cx, cy-1, 0, 1); stbcc__add_connections_to_adjacent_cluster(g, cx, cy+1, 0,-1); - stbcc__build_connected_components_for_clumps(g); + if (!g->in_batched_update) + stbcc__build_connected_components_for_clumps(g); + #if 0 + else + g->cluster_dirty[cy][cx] = 1; + #endif +} + +void stbcc_update_batch_begin(stbcc_grid *g) +{ + assert(!g->in_batched_update); + g->in_batched_update = 1; +} + +void stbcc_update_batch_end(stbcc_grid *g) +{ + assert(g->in_batched_update); + g->in_batched_update = 0; + stbcc__build_connected_components_for_clumps(g); // @OPTIMIZE: only do this if update was non-empty } size_t stbcc_grid_sizeof(void) @@ -374,6 +442,13 @@ void stbcc_init_grid(stbcc_grid *g, unsigned char *map, int w, int h) g->h = h; g->cw = w >> STBCC_CLUSTER_SIZE_X_LOG2; g->ch = h >> STBCC_CLUSTER_SIZE_Y_LOG2; + g->in_batched_update = 0; + + #if 0 + for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) + for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) + g->cluster_dirty[j][i] = 0; + #endif for (j=0; j < h; ++j) { for (i=0; i < w; i += 8) { diff --git a/tests/stb.dsp b/tests/stb.dsp index b5ce917..bc4cf60 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -106,6 +106,10 @@ SOURCE=..\stb_c_lexer.h # End Source File # Begin Source File +SOURCE=..\stb_connected_components.h +# End Source File +# Begin Source File + SOURCE=..\stb_divide.h # End Source File # Begin Source File diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index 3f4148c..de25330 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -9,7 +9,6 @@ #define STB_RECT_PACK_IMPLEMENTATION #define STB_VOXEL_RENDER_IMPLEMENTATION #define STB_EASY_FONT_IMPLEMENTATION -#define STB_CONNECTED_COMPONENTS_IMPLEMENTATION #include "stb_easy_font.h" #include "stb_herringbone_wang_tile.h" @@ -22,10 +21,6 @@ #include "stb_image_resize.h" #include "stb_rect_pack.h" -#define STBCC_GRID_COUNT_X_LOG2 10 -#define STBCC_GRID_COUNT_Y_LOG2 10 -#include "stb_connected_components.h" - #define STBVOX_CONFIG_MODE 1 #include "stb_voxel_render.h" From e585dad291c07afe6dd955d4c605fe57c69243b3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 11:21:59 -0700 Subject: [PATCH 324/522] change map image formats to workaround stb_image bug --- data/map_01.png | Bin 26064 -> 30625 bytes data/map_03.png | Bin 8747 -> 9620 bytes stb_connected_components.h | 2 +- tests/stb.dsp | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/map_01.png b/data/map_01.png index a2be8a0dc73c2be249a6250034362ccaef2644ea..2da3f5cb3925b0fd39dac2f93df1fa8d94d5a09e 100644 GIT binary patch literal 30625 zcmV(>K-j;DP)V(Aek`hzykT254|TWTmJrE?;gP29X&Jvma*_jOG7{afBwb~H0}ij!gIuj ze+EH+6M%nQq{(;Fe?Wj-zR`b4Q+ED>tny0>ZJ3Rge$=v6(qTYAZ~*`QL4jg23lPqU zR4n{(n-kERZ8Gv4$3Z{1*c$9+cO$>mF!J8fd0Rd*r?!pGn zY8Lq66840~9scsIv$|vz6E-~*0s{DE^kdfDhjJ$x*%WBRT*DBs@)8DMy=m@J1+m*@^7dYJ zCBSqG1eoYjUVsO&{Li{H`PNUj;f)Ny6X^{>{Q&_P-Q7{C|1uN##@yv=oxe9}02V3P zqAo-V2#8F>N`Ja3al7ibog)3Zi+H;J8W0p*S-hJ(G9moO{s)iALQ?XR^NisdfR$^& zakL=lKOi_qHVN_>9;TE8>j~Q1oPb>7k-nS!1H%7GMRQ@lat5wtAaer);MypBnDrkJ zlGi*2mbKl&RZZ(O{s;)L?}gYZ?MlG_JRToQFaQom=L7YD zfB+8z_w0xgYdj1bUPrnewk`|Bp`J0J*LZx~SAL+oyC28^@-$!M_zwsMKq0>6sh)Y9EBe9P_`sHiLOA{d!d+km zFIhYaP~c1?|4f8;*!}_GX_cn(f%1_b&WQ&8H`Jui{NEcPAQ~@GBw9Z|TuuJ(k9{Wr z;P16#V2fT>0b%L4^xVg4TCl+=p3VT+X)_O_^?(5Ba-guskHQoFFppo8-{wjTfP(w~ z*W`adfUU=B^NF-b_cYntTBj{pv3Usj2Lza~Bk5-{FDS)yJZIl|nSlNti3dcNb)oGg zx&60Q#LRpXU^c}EFn8gjM95CZV@uthvQ{3z90(vS1JUf0i)k*HuO|QNF-LGrB~XU# z5riMW1sxy&XR=_6p~uWkm~~$Me~+O50IkQt02g{LDY>9Jw>^aT!v=RO-UQ%PUI706 ziW4CNSz?0;@;|*yE-(rw6aoiuTn=LyVfNzRf6o=#GXU3c0=ky84K6^s9|EKejX8Lj zOeef;QQ=Q=O-{hXg;~!J5P;tdHY)78qibc7L~*v5a|s3z#mxcd=md8+`ME0&Rj27O zMFVjDQEVh#(63CD6&?_lgNaJ-u5#`;h-TQIq>(SZntDXD31D#{@*ntfZwDS4qYm<9kdn(Vq#IVOVjL(=68gF99?!u4F8^yuget2L=v~ zDBA-7e5t+U7tle!tP?z?zagXXEO@Gn#-0c!U zze76ri&gK}=2+9Z0yBXFtn2pUuw9d{Y<3>N<*w}>F@R%i^4||k2m_X&G!=QVd)y!M z{D&LU#I*}^vcHEkzULx0lhM`0B3htf<`jn zdvtB`j$?7&Ke^-n{e!a!HSW9Lo0HImMKu85rW#V7(>^!)+on5h?l_@dv_A)MF~MFx zcq*ppJVM!ST_wx2!#O*Q4J>~loObGSeWx|(8L93G*8!)Wz=Vb%196O9+}Y*STq8rc zfSfxN}SL3{+SrW?1aOgRx|y|t!E059H2QcmJ6_`@$I>aV;`0i zLZ9b3iw|y>=1#TgpQq=-N;5lK%2W}kXXKe}W0bsf z_s+Lnf^eg!$Kw`-z92HtPERsX11KVb1%uzOw3J-eMP{qWH(!15D~mY*@FULQcm|D8 zm7F{9+{6L4*5Mr(i2RT0v6{%dk+wF{Rys$h zj~{8?ME?03+w^$fRx8x*yv6$%KpqM8)XkqI!IaovMB(8J$HC3*K9jCvMHb4@%ZrXj zL-LHq{y$!2dz8b+>W?D%F|^?81lkR*%4sITCs%rd;%tvP}Q9&pW_Gt%Xp&Zt;#l{!~@0`M>V` z1gr1Dc6HRADw@O*NPSbj%s1s40s68F>c_j+_&B)Yp|%}EtWwUABX#)VXIkQvVDbCC z4kuCk1uMV`tCC|XbmuQ*m1NLm3%X+2tsOhoG!9V|;g#eEd$;$g!fkez<0JTDaF`S;{=u8E< zNk~|#7%X#QPg1{1GD{!87dBNjecBNc6BcIc*CxV`?laflR9i!VlpP~*Rv%lH)e>HePWT6< zx%9W)JU3TH|A)`?D+O&=)fazTz^*hbcPvbG{z~DD=ygRtulG|@p zNb|wO@pmK(w|E1QZR-&}y;ID(7NF^-? z`*bb$vL7?M=*oxZ%K|1~Cq<>c-U#r|$1zy9rGSiSSRi=zzdj8(&BEt9;N-gIZA#oc zR6eFx$^mbpG-(Pe)0qK;0zkq#y5^Bo@0qQW37!J%gJ1rABFWpC6&7h7pKULhrRURu zQ$7FKf3Ya|WrsbfWRraO_HwVR;tx@jcY%td(uUapTj^DlhQiMNc{sA{x%T7Kf6on( z6C#cDTre@~b@G>YO2yhsDrygMlL;WF_=9&-t9QAqo@@M5@_CpNR@-+|EQ1zK$P5-B zwFAf9b9R2inPI@=bOdK$Hg-frW(eT*qhWZwx!%bM>|mYay|$P95lr^R2DzC5xQ-W4 zcI|4UFQxEkzbI9s#h1HyO-yiRNLIE=?=A#mCms&Uhru}=L(J002}4%Yaay8Fadfy`$);Q>n&sYjj&{s)BtQGB<#q1r1)$+_j(z{05Y-fvJ#wV zqDm!6JHh;4miCVgQKm>~Z^|4baVW@0IC2njc@<`4DdgXAzF1;YU7?pt#qmen8pfH$&66@n=-VMt9H0RIXYFGlkD#Qw=k zf*&tR2H9T(%t-fRD`CA}fTNj#e?}r7W9y!o7EY)I@N1$ARu^X4S4|Ay$iF3Jy*XA6 z$DkYj(FaW6(V}w^?HSAf3fiQ2euSpPOhZv3Gj6BD$xAJtdMd)vI*DMJe);RuVHizt zi>=0o=P=1oxT%xMnX@0nna@#gP8_6qc$NpO(;V?R{hZlixcsHb#%cR)Bj zjzMl$IVEwBeaX%=qh_pjRA;x5^mi<1?8c1)0o%=layeboLgPH8dl+yg*i-a#z<4lJiN^$1yqaO+!nw&uIWF>X zYxu@)y^R6bDlKzwcJIR-_OTs*w??1chBm2@KALNo61PuLyoh+_QBO+*vK8$(S@&23 zGI{$|C-rFT^j^!b7-EokYCLjquhib&U6^h4F^yVswvGHL_a-X?Vg65RnS^8SXV$?+ zq=e;FJmvu3klo_UCpHDG8P=6Kn6Z=cvjXaMUS6blc)-tWHfzTV75O_hcMrzlO;iRt z;=J~5v$9Xsqm1OAb4_FXVTFb&Zc={M#kU?KIOk5{V!a(@T|sBcih?ZII)1F@i3 zyc_}w`XDxy1z=stHSX>#ycxgUz|q9$77*IHEWdRUp0gA2prpvJnI8fE>Rg$!h*`^` zx^EYMSpj|zF-YeS#5NP(IIl@qJ&d6KT{Z=tMxEeH@{ z^0vRDR*8->s1>jS2hw66~y zl?0N=zu`c0hp$2$&zUo38rmgZ;qI0`QgLgUBxhdEEMg9|ASA{pf`hOPuJp~KV+o6#J<-5m};fS3hK@nwK^4;qzHN9Z*n?pH-RhE|(0ptx%my;v|xp5(ecx;gk>`>;uGtAzVz(lS;DP zr{mM37_PF`mwYv6_`T;%0DH+!*YoE4ldQ;;@EmU8i+cR{{lFNkC*b^8%wJsgE#t*& z7_?biJNbv^{b1?o+iU|;;&h`bJgpK)!VZn6NH%5>(=}1!zjpd3tp%zn;4nMGUrTW! zdHBw4qwP*nQJ0AP2r(9}}pZvhjrOE_&A0Y#z9|r$H5crHo{1W|V z@PMMGi#6c#8`b>59?XqLX5j{S5Hs?}TCI}&nwL)mz>^AZ>D2PM5<|bqXQX8UXL8!wDV0&y;`Z+;8l^c0JZv#*PA}n%@nR3#bFD}wbjP9`e7R>APoLDfq1kQBo9q(=~GZ9x0qeH zo9zA&0V*;99}A>_fO2-8wIqrkDcjkdQ~5JI^M{5^z_&nvel%JG>}BaNQgk`;mG5T& zVfK53Nl-eiH6`GUtOE`{l!%WWrj@Gp>kp43ORCwST0Im+% zscwIueW_{qvdIK6@=cyp3_&tu0gm_iO4r~L2wdpM5-;DX)443@u>7^_| zt(T{J4Jm)1s|nzfg?uCi-D{dTtyh7G(i`UM03B6;O!;{IJb$V*u_r??0AJrioP(IC zjb17*4udi&b;#b_+jR^n2PQoj0(6I>rZ)lyGpB->hg8RK$DAD%1>ku_!2uqjz3-jx zP9xrt2*YcF>>^7gjfbs)@Ylwv0AtdLx!S9I>q zMRLQ!tKLks(H_|F2OhO6%Q-;|=c43WcTMv=*Lj@cpzwS#_S;Q>03%9pP@u##t%&m* zb)^ZhU$4W$!?u@Z^8}DQ{5F<_``AyJ@6L?G{r9euVgvS$e<=8c-we)wyE^P_v1aNG z6X0DL&U}Y6Mx;Ay@PIQ=WB}YClTC|)FH37CN(a`% zHrWl#L~j-)C-vejT4lZp)j27-a4wOAQ^_F=*?(WOdzpzj48R9^;(To-pg&g}DeK4w zzxpHWW1)C7PxE`JU;rUbAFTWso0(+MLTkQCIO(MT;|F7Ri!j{r=9&Tm?kE}b3#Cg3 z+CTI!Zj1M*@H8P>)a?RD{%`{nS#u5jXM8x|`5YJ>+gm)i#t8ru*PZ0K;z6(2#fu&P{>(+&z zPx&$N5WbE5IuEg8Mr6#VQA|?G!&ND@@a@(P0eEs`hU2uupWFwiVdHIHZ#)z z==wNp(@Xwa4-;WOOOjnBQ5-v*8BPMu zV*1j?06b9BGe=`W)~<!FIg8VO`M?-^I><@x&#CkdIv}}XV)gLAgtT0k4G;dQ zo8PL*fB%CwI^5W?wrDr_32dH;HD{0P_GSnNVC}qqTmpIIkWcOjhpliKAL-w@r>Z-b zj^sJ?Z{EQpT(mP)?T^9i1^&wcNLHMP#|qtUEL4~lrqO#yZap2x`}-KkATT9wrhnfQ z^p|lbhER-s+xBo9Nv9q5QEMEjLrR@>glBld*1QOI()vB=w{fBpXH){UkrX@K@-q9+ zoMi0=ulqrI)s0@H5WY7TtZ)M2+4_B(*V-Z%@iuCttn>4p{(nwzsIyz{))(^xzRV?M z5?kJbWltqFVL&YMZQIC%>sZR0WHMc}Q`SwjZ&CyD%||Ri4mgLu7WMR^55S`@{T9o! zT3S%>GLT$|{Ea$;LUP+)NKixtu1;HaLEJUt0MZ3#<-}9)Ghv#*f(g)=wrkNX$l;gN zO9}?0dU^HN0P}yA>%J)wgBP?V@@-DaD`Kd%Dyaf#i*ahn`ty4ov`drIeON<3N0NlFm;?8t-{8cRCjE0lp5b z6O7r`cOI4FDrcR`SG;1Y$=KyEx7hBe?JSF*lst5A@TQQTiwud@ByB&N6u4AApsO55 zp21@ifYR)wAfH>fn%|h~(j}zw3i80z}H%*V|hA1}Cuoj98{`GM?00OjHwdlXRs; z18{P~CC8Tqywd_m_-nj_+pyGwI7B+Ar}Z*HQ$2I+XaZO@FrM#tV?buZ%(-}u&tf$H zsRyZAf2m~woS3K|(jwedQDZFw@J5m)O$C0|OrVkjtY3&D3$C!$OGkB$o$TJabA(_= zC!owEO$h~HUb>n*?@V28t+&a5Z3B@J2I1BLOHBOE;WEBP3BY#Z2s=RP7n~b)R{S_h zlBXE}eh$YwTSj`T#vw0gjPD^I=j9H;`B->U@FAbOd&B{#)c`p9+Cj@bdr5h%_0QjJ z!XJn*I6Q}RJYHb^RdPmtZPR$Jlf+Ks0`P0e&5qLHNY0jYWe$J?G6B8VEXKTUZ-4;9 zAXpEi!~rr9Zs`v2po~CTwvh?AZc6w#TnfOEt{fJdrkoz$)~R0JR0N+Pa)`vbS6e;O z-|CZx89jN*TPHJ;Bii)AAtOK1yy?||FHdkV@iV(8B_^?Tw5zBj4%X4QEPUycW8tM^ zIY_Su86mLqQp!_PBL16a4Dm2?i~P@{=*ImY+EGb^{Qt@TM>D2<=xSO5I49#66$a!q zLa~s;#a9;xnkCgR6E;_IyRHbt5y`70pJ&3^g#nlnyrx(q6~Om~>!bm>q#y!*q*h4Q z2n}J)jJIA$WwwbT#Jvt+)m&*`C?B#K^710Y(JjGz5vAa{SP*Y_>Pzw(Pc)LDTx`op zNsk+LbV~&Cz1zC~?9+I?v6=VEY7^_F1Ce+4&zGjHv)SxY0yLuK0ilvOCKHes_0+F- zUHG&dm;kw>X@n1R18g_RN`9qXj*HEeJn&!!H%uR&q$uEa)0AZy;&5OeQ=eh7U^i4{ zxk-nA1J71}o3^`x>ppuuNxlff3_nJ*%4SNes{i3B!8SGuzz-Cd#qe2?k%UVG&t9}O zcTuo#NYHY?HC|8Ar{t5=UrC1ek0uG*2>Fj5U(RFG0C+){P+4pE^W)_F@KMotvKr8{ zzrfMulCdN?Qy4w~vKKB!qA>!Got@y;nrIrz7YA zJSH7rYxU~A6f5w}$4qcg+H8Fijr?+T5DrE`F6G>EI6k^%0{V0eh)4iddd8%1%uKIQ z@nzw0rO*Wf%fslciZI|{kj$lgcoc~*)KPa#%5&8mPiz+sUU~|$knEDhMI$Tnl%vnK zv9%LR>(Svb!peP>e^8!Q!OXRbNQvtmNTuhV;zAj(CT{Hqz?<{S@a-IeWJ?g8X4Ra& z8iO^~oZLc*yuKlbzfmRX8N%VgEWoDp6r0TP{OIAwQs917)GFr3u%+YvedP32|0@TUwqQ~t$ik<^SIfKTl!eV?Tia)31w<?B9J!%O}e7sZ! zs*Qeg>G2is;(&@*TR9IX6a&L5z~r+_F$JR0bW2K zCVr}ME*96w>5&mjISRS5iG1acMgupJ9c8K|`sXPQKn@4&FV>fus9IgmFPfuufqe}m z-nnP8p1y!t1He%VwYzunxYS+`P&H20l7@IA-m$Ef{EsH?Ctwj?Je1X|3%*cz#T z((lpJ>3!XR%bE3L!*B)mX<{Tl!Ee{Hs4Z)vy&=e}4+pGtd-E`L9S2EP6BR<%nIB9hkHwu6Cx2mFHG-{RwB+=RVmi@I$OE8Ly`%=rF zK&k8gcRaEI<_xIq2tIsJzZQ~(#_wA*^|KxsI0Ltc-U#Ef<4Deq2|9xlFzis&|Arz# z9N-b@4klOIT9fMa=c1mppqP!1z}HD`JvW7SN-|!a!#f!4+0@rTLz01$mxcBi+ckjo z359OAsh+-7^_P?Y2c&_)(u$%fQSCZ#4R4?yc4m8FNSp!KV5BqL<*aea^kpOiktH@+ zMwkG!$&puj4+A{OTAXJv`=?EaR8R1s8~{(700CasIs$m>anC+{H>hF&0d&1sebuSw zv_6=fzh&jzKzOP-NZu3TT!1m*8h+4>@WGN&ZqZk89cPbx%L54DT6qIMnxx>P<}<4< z(dBdif&q-qxh|(mtIs#peIi+K9|wRntpI`n44@#@TBHwWop)2oj$NC8VXs=717sgS z0JFk^0r>70vYx{Rg8@uFnKJ-iUi##cg|dCY$t-ue6Spbx#BxG0DlKmX zPecKN{`HEIK<(+Z<){04iL_qoU;ExAmyQWW6rhXuhtKEC+mBN_%uEfyYe&UehcdXF zKgS3I_9^4CCa8E$Rkte9mVZ%`n=^83@b(*t5O)F&)&R_s@W+5Zi|fMG^U~ zOy9(M9AJxHd=H@l!`0uP7O?iNCd!i)bR9=90AGqCXrhZ+Y3IX6{AJ-z@=RndUrT?rqSV99~uc4Q0fN zkuq>QTa_C%074r`R;M<&>hWeI=cua`U43QXlTw7Amx|=8`T*6;X`4v7kz3}^x9pP| z+NO;joaDhWC01nt;REoqo`(G>+K(t~53K}$rbd>g+uU%JZEN{uDmoQZZ=QWcb#(|dv#ZzuqH%XaCIz;u=yceQyg^K z5x46D(6Ut2U#gFE0tUz^&BHcybN@rV*TR}1IMN1~o9keX1WI!lPs| z_f5z=N#Cp=6eKwzZMM|r!d)5 z=05>Xy4QTa+6NH*ylv31flGsMY{oICt9R+(+YDIO1PJh|66gCO5+tX`ZRR^7d{0rF zM;btYttU=0n;6Esx#_vcK$;7XXZ3FS&#>{JVD8#O^$-tu(E%&$Cu({);JDJz_xk_> zD11p@>gP>Cc$e8hHLV0{_yE?id96Pk$sq*GHACD_$F@4ferHv^rd?sc*?Mp7``Jb> z>|=nArD6>86;eB%OKI*5-dtZ=u`PBFPd-8e2=Ew-q(6G%#XNJl#e~KihA>OodOTOV zD<#q}M#2ZshvHmL%E3jU<#;g(+)9+%XGKxpb>5m+G=Ko6-7aLkFZuPsv^MSVmT8h4 zsRAr;?!J%qXl&60s1^A5(W?7B)AL&jRCbqXNrgF7LPwu>EF5>yJx#aT!T^E`c$$ts zlBw5moGZRZTvKM6_%J$>J$I>B#0ArffTuBl01nT#z}uKG>tFy2=NtIgm2kmqTD+qJh|Hcbh6Zpeu%rVa1Ks9< z3->Fu=yW9c=N_NSm@RIT1OvFk)5mIJo~xcNPW+4~F^lAib^!L^x)xqFK1}3^0hkB| zFc^km6DfHoOX2b6<;id#`S{c%FHZ}VU;xX5NA!nnRKWeVwkgqphtW7X{G@`IxJhM` zSNcDL0q}rAu|X|4GvHUP$GIg~_~q^L8oI-`^akL?CO~`9gjX1VgVwlA=4W?A z;XMYpJU1PHp!k$HA{zU&&86#D9h~CM!1M9iAMb;5#E71NKj&Q3K?UpjwAFxKy%m~R zvac@`4hEnO!FU&(nWo18e~6w*tEwp=d;q6{2fWtKA-RnAPvT_R&;TZDTB_!I7uHqu z4Xz$%KE?rEw%Pr~rSYnv0o>1PJ#`}~x#-;3yD;rTI3`9!%j9J$0R9suatdP%24H$G zZPLJObr;=LrlQ2|y+@2(t& z7BSucPHoP_DzTti1`r&8*0(iToer`>tm}$Qb6;S5r>m#kor;qj1 zS%v`wI56v*+eI*W;7Oitw$arY5J!n`-w-u`O!l@v$ZPC}r#d>Y<2b0i(j{btq%>M@ z2@QZJ4A26L9XdJZ#L$^oDZ|%BNZiHztuFp}Dl1B}LPY|u*i z!jKqh2rztQ`+1bNTMI@b=E%?WUTR)BhaF?yPWyh{Y1fL&`r$L-1pJ=S@1SnBOfYNc zGYb>XtoCHU%989>6e3HpbHfps?1p*PrXbLNCUlz;wM$5kjo{Mnj$)~PAa>fGL>dX! zIRS|*|6US88tJ7Sczpd07Z;1MA<+DM9+M74^42IoG}O1^!dd(fM=J2rIuBD~DfJZd zACD+h~5bh#71 zJ^Dl~6LN$DP_WyxWp*AwUgH3qu^1+XS^iFuL%2XICl?M>;56~HJwu9e=bQGyKaw}h z#WWG9nx*AQVE@Ql2Ku^VXA5tfr2=dx);RKl{gLct>|V+E>XpM@G>encEdKjqiU$1y z_qz*V-m<~!yUK#B!zU7p`rS$-(f|etGUhp6Esx2DIpn)B|4*-hvzj%Tr`vUBxKZA0 z2OE!l*;=?5GRX5iukt;4-vP&hv#!k~Pi zlldUe7F{H_yuiO)PmEf?i>O)nCW>xSKT4e+fP4w3u^A7pKtMHi_DYHqF+w8iyxN~ zA}33RypAzsF9dJMM;kv4*+}keClZnEaUM7+rixLLGw}sG-e_V-W4ydqo1Zr}VyxI|5_0Wy zVY(7YxxtHk`*E%%C|5kkOm(tj1sRSi!j+Spa(j4=|9s%;yzJ#VveBz*zb&)Fa$4CY zUluD;BDs^rYXYYjfc&N_5L@oy96`u=Q;5MV5?_?b!OXdmoZT~A`lSLJMnFZ|dfVQ^ zJPvB}LiqhR7UD&`w?r7W$+pZ3--ge)d+00D*J;C#xoAfp7A0eE-c~uU$Fu@iJutex zl0m%21`a?SYT*Qa-9piEs`WXg0|B4h~CK-v=PrnV2#e*DX_!16)H!kKjA?~-Z{?8GG;U&V9liEeQ-$?Sn!W5UXw-D1H`#j2 z`cT#YFeUD>q1lnp3V{3N!!I1mixf;d&8@F-QR~3OM>y?FEZJbt4+Jd#4twkCk1Bu1 zcU8>gBQhj=uwt{vqXn@X=WoPXthaMjE%u~cQu632^2R`*CvM)pb+e#F82R-gNv==+ zBpb9et|kDv1Zp`Qjjecu`>iu29vH%NOez37#B<*dfVQo#e-?#rmyXMDY&22a-ZS(s zJ?aQt|D;|%t-0(rz(k$7>4zuFKR@Ho1RU5c&wsn0+X+w`?i&PZ?bUfLU`KEVBmtxo zkhz3@TW`Hi|4u?L=(W9`o|T?_2IN0qT|UHq4FLAbv(2+wC~oZhoyoLnR~g{vS-X3a zObfa9SKT~tyVJ?ZLBW3OwWhu&8_@r<=ps)81}XvNxR<8ofCk!WSvkvi2ur6`*V8qf z3brX8brP_RwwiH?j-NDMy|*7}U7q{^@oQX!`T(GPDy*cd|4crfASzv033W5%)#}GDgd7OWt;21 zaDvE}DK>xw8ju1TaIe(UfZ$Zj)|=g2$05DE4t71DUEX)V4au@d-G&JamtIRR^r*x+ z?uAT*XM`U81;5?;f|}S}gLOl)dCumf&F9zv(#3`7KhxcMVNHHEE9swJsb}F++*n2* zf^1?wmvl;@rQD4uriB4VG7ksl0r-TxD7jR(Y@(T{_#S4HQ&`Szc+P@+hJQ2-+Vwz^ zCSL3a^w9F$k|{AuS#j2x36MM`rB^Hz5|t`P+g zKcfSdj(qR6iBE_|F>Yk}xg;i4e)tP#;F7#66&Q>7?A@#mzwNyT2p|QqKEOdLykF>W z{ROrU=_i|mJMC;hTs@qE=_CiBqTgY;y4u^2$V)d+T({0TP!4jC9F7P0I4WiU4PwtI zfV+?FoRk5!fu*ue9Dbai$CG!3urftF!oE4}=0} ziDqwEuwgQs`d5 zTTcdJxdGc<1h@)=^V~V^k{0KsG}w4}w6>l?G)sqH(6F(;WLo?;hG2PSjMY2U5K>|_ zrxH*elWJ~WbT>7@LMchBgSU4CqS0FRL&S_0E|0}4ZEy=WP7qTXSMldmrs}Aq1KOvC zU5FeXA7B%yNA-JtxQ-;aJ{VJ3boxqsm-N{qVc&oH-=4o?M8V}y&fX7a> z#p5_Y-qkHV0p!}&ng6;J5^~JGa=w0^yLKNqe;x0RpZu0tq8 zL^I2D!DqMzV7H=cn`dM8fq9L6XC%Z5bd@>EG@px&DX(JQGDiFE>gQC2Gt^m#?ogLj zqwxL7!;CfoWK>v=3wY#Ne2|P%&T;$Vmzl5|7dHwbyDG6Z@d|fM0b2nJ4CY4;2lc08 zE{;4Xhr)L|oRj2k${Ywv9woSZl$(sR2N$uL697*$04Jh{-5x`SMWne!fo;V_xHExP zR6DUZLl*MPsphF9`*TE|-DDI`A@Ak@1jDWqDShujH9u9e@njv791C$}I3N|+@rtBc`6Fo>1aSIWolAb|icEnvasiHs z4@hYnLjI2ADh`%VVoJ=$1$=xz7VG*2$t9YgbHw&-aE#58NLv?#_Ep&e{vkq=r8V`w zR9bwvRwJvI$+DDF5?kNFp;(at#Xz!HPedD6UnucJ#x$_tx_;qmxf;ti;wO1|mwYfc z-ZJ7o2yhSsdVgbSrawx$ZQbsS=Q(Wxai9`{J&_oD)&fjpnHKO1J7xz<*M7h+0}Hth zR#1&Rls&R+-$A*hAqW+LZyuCk?CaVj)A1I|Q`4&F`nHhVd|dHs8ixLtV+CEn`GjCH z{W!SvYpnVyfRUT@-~B^Yf0rin^n;tw<7L3lZ~%KOumvAL$iI=myB5IyF*AQYdkedH z0w{HmdTSUEhq$_$f!8r0TQ&l#uqaf1>6wX%r%ZszHqjIiu!34^SFQ~yZL7&?TvZ7U z1)zI=4O2HOI0_uL1Y;VG;d-`!k5Ws0**T#BIINq~e-p9K8)Os@AuLs+`Zb^sEV3&q zYueVbzv+B1x9hnAY0Ez@U+MZBLMAn74Hdw@Na7Z}eknrn6qj%%SdnUqoj%80264zJI)4_R~wt&=PsA7@8ku-E^Gi<@o-QaP%jwZ5)2Bb zTetx@2A%#}Mq_~=QqLl_+PVy^0CEQJ3y%lq5ki5R-{l24;Qf?pqEW%e@xg!q+ZaFq zHzdvR@rC&ZZXUk(p(e>X7T|9wWi%ejW?Gy91hAaV;R1H9oEVmga0RSl0vHOwg21?q zA#DIwgm~l4YU=u(>=*C!9Cx3sBQDhDlz+eC& zau?%F-b(ecTbsHunn%RGbJiElSv8+=iU0j zzWMW+WYz#42?1d$d%dTW`qTTb|Nl=+hypapn|w(?csr$(gc3M}hpE@3l-MzV2nmD& zz_PRP5XHRG!;oLiYR&Wi@A>j32J9~wB0%>=Gi1P$<-nL80s+ji`a4xD%1_r~`&9!7 z&r_%&E`t>ukA~{U^HT`S;u?TF*Ym*7i)T5zIW}9Y^3OutrK+3(S=ahhHpbafHzyZ1nwTr zmVVWM0TRxSBnu6Yiq}O+@B{`Bt(l`zsV(e>-{#=GmkKq#!G*m#HfP-U^TAzP#eHS5saxk#c{*Mm7+(%03x0mItBNU zzu&zNriA(H#G?E;7{F`8wc(%e&SVi2J)a)60P}$c3=UeG4mxagJ+iS#I`0^;Ch#LuB(J2sW) z#~DEA?*Sgu1cNtQ8Zk?rM$DlBU<*D4IQDtmx*vYc*~230n1~#p%RYec@`Y!@2e32# zmG_!&Rh#KQG=OLa9)Mp7&WPmKq08BhVB;kBy zbI^k*>EJlLs3+j2qN;5@y7DGW!3I&3L6Rx)17-=$cjGXO#us#!h*V&2l>N3OxB8pT zLv=Lw@Z=?BChh0Z2B?eI0{AFV>RTKD4AUQA(4J7}&0xw90Muvz0sg|^tZi_jbI8BU z4?MX_!2|r@1Bmkhg2^$WP>VWzkXx8wfI~F^9v_fl5)!`bwNQJvdRPCkfbDf%d;=KR z?a+J1V&Y;ru~5Do;NSnZ7a7PH2Z(e4`|UZmw2UBm_VoeYng_s>m13hu(M0l>)7)M# zi2kCW*?zm0Hv$x%#~oK?{$8emK#c!F>kT-UN#nH0U)fCv)QvJ6MD#EL2t{GiLOAL% z_IM+6#2)_rhF_IM<>GDrcWUA`Scsd}g@^%I{?+=zNTzj%!SMg%cP5a(ph*MpcKXMs z6CJ-`ShCzkgaq*Tx9y%0`RcvpoYJ+v0?nQugC_NbT*L{U|50xXX<>s2FtrneDPZZfAkr-#u^}e9FaS!cjX$EA@yxOK zOYXOzev+S9z&4oU5<)o!d|MpQgF>QE5I9Pc*g^+;lNe+c`Lj}AP>EWAeWT6KDIQw{ zWgm)f;ZWh=SfKC($e)G4BP_M47Qp8-1Gj>V~?C;thhf)FdyPIS~Y>wnyl^YLc7eRkbiG({174JM4Bvb%( zUG71XU!3`Y7pS?==ne=2GyqHo5a4S~c=Qn=ga{7c7ky~!CDG+2j3OG7k*w!KOcofp z8y%6Wy2}A}To}+qgkDz%JMS6pD6U6`7+RU0|941{D~!XU0O}(BBEsWNd9zN9(zCCE zF^$6*v=4+f*!yU(^0o)?IG*Cw8OcHm7V?L`DgeC`fyTQFF%*FDgRx(aN0~*X9*&LQ z6jJOd$&v=JJ^@AgnbX&j)@txfmLqz{ctVm8dgy>W0DfExb21a-9=1T~g<2cMCjmg` zO<>1wq9X7{4IuIhT*>8Z|0DmT*$|*VvP8gnzqP|^0jSYjnh0Os=zY@XxFH z^O0Z#3Fw^&L}oHSmNtkFGH>iHf^q3B@gP$vfMgd9Ai(lB0IQ9awnLlf8d!)p-+T<% zx-EKuEFTvkVIe*ioBiqxK*vM@)U+ss3&06)c9oKM4XpUKFWVTo6cL5okaZQH)1)3) z8W9HunYbqm=%Tu!vtG!uN5j#|O?(XQdqe`!w(h^a^2Pr22K}Ew>JGq?E&v^_7Qm`~ zucBxL*y#ZSqX0g{DDa*)xPAc8i}+MluT>X2?IHYB7EFL86+)w^pnV!N8tM7{=byJ|G}t z+JdvPvLiT?@i?2s(U&+$iQVo$G7cQDb<*oxI`7$=I4fhBrPr?Jc*rC#kAp%djy3c? z|1!Hs{)KHgaDEwoq!}DX%JzCWc$Eup#Of8faeku zzj)*fpF+7X&Iw3LqZI&L8@If9xLl%t`m!N|?jI=Mw%Z5CZIhS4v9aUwvDRDwUSt52 zC{VnW03!^|F^a;Y0d?vi#@@Y$RP&_Rpe)7g&8MUA(CrRFm?>7Ql6q0s}}6 zkxd@Ghm0^kWS{em{`|i&X)Z;|t!w*2k0s~Cm^e0i);9yf2-qg&TNp_|VYCc~Xb4nD z)1>Xk$cs2AQC`G7nkH8G-F%2#*i0ay+<+{XUcYVa?x#QQmvRqcve*nwBd(`m;3v zcd9?X7>nTv$px;sF&?~JBLk8|N+!t|hF@J^Z?*yaZ8r#)>J$0GsCZOg zDO2KMGUvb6m#YUjuf2}U3h>Q(k-Jau?Gdp{z!VLjJa0}1Ed9yEAiGNp)^%lhU2uBt z#4%hh_d}k=u(oN8Fu+J(Y_$(D%?BQuo#b^501v+O*CG5`Y^y5)p3Nm=xOVUrxrrLpFuDOTRp@<@HN51rhX|-P41!CqiSx;Fqws`EL2+1BKJ}n(jR;%U=A9 zvrOQc96l6>H>SpH?(;@bf-f`y>US&BvH3C{=PfKdk2ZB#yJk*%{q5qMUONF+F#wXc zNNIc*{Zla-nKLhIB$%`egXAsgRivpPKN|&b(s^-FC`R`YVe#^o>K^R79;8+XMBGMW zt);YBUw#0X%LxvT35aBOLzf?H6%}~^hF@?rg)`#;bYVQL?{(2e(72k+&jBf}GXUxY zp}!Lsm|()sUpZVvBrt=V3cXCtseS|1ZsO;pa(J+PtjqIj!hqN_09JklqYxcuo8U{npGp;o0}aAo z$o%x%ceuJD>o*l(>yBr*vm?nr+^w)P}V30LoitWipSHxE4!lc9Dzt-+;;S8M&OX5$e)=$DA{5E+0K zXdGCX<=2`3jE)SxLJf*{4ZQvdgTnn!& zM6qHfUbnhgqqS5djp02EAn!HbxRJ}#l{lILnWzAG_((t6__hv|pE*f2ih;Nuo5dUS z@n~UYr?!S9Ptt#+R?iCQ$OAm{(!Otr*+ucaYVz-VKQWjLgc*mvDM_w8MQ z$ETL(crYJYDaiyjGS>oNj2iFwQ*v1at8r3I02Z))E#$mW15mAt4rF%VGwA;n#spLi zwe0(6#=M-Q{PBFHbDKdO3?VFBGK$`^5)%O{1KljZ*|4u804q5U>1l~$CGr{;+JQ^V(75`aJKYZAgu^iUXCd-e1-nLq#UO6@?w+xVJwjJ zEcoxav`l&hIBMoV;YBpPlC%uKZ6l(jWGzNe%+vrll0QA932)azTxj5|&VTVP`X}#= zq=&=MYQXjzc%T(xS`lp9Knle6T27qLGWX+KSarkmm~n~*KoR}UEhSdSB-028e-d@q zklq9w@W7Rw02Lg1TL*{yI1j9R-uu0o%;Y{kg6jszt~g`yD1a5;@+!TPw6+#W$&=_p zJK`RH7`pwe9{nS)%q#}LJA*C!K*WS*emoy!u+!1IaI=Ni`l395(K081M=vn9zQZN` zLL^U(a+^u3O>5|M47DsGUq(Z&FYrkw^AIuH0h5WceIQ43ixUZW+d5nR zac_sqeR9&`D7V0?HPH3}?opTCrz4j<;{=D_5ZP5^iYr$Gx(xY?9mKaUb^-WAKJCCU zd+N80A&tfee$PPX!)Cd3HK6Y3pU@drWgb4-KH;tf;f|H_T=xdo?g!w0&BmVbHy)h+ zAb;Ee_*db_|0jZZl_e{^c70og{L52eJXMgqn{27nteLMxuMfDQ5=OGytfUju-<}gu zvRHoUQE?>a_XSA;V$-if)hF zAsn>9xI#*@i$@@zm@Osu`2KLG^7k*7r0<4o&*RTn_$6Sp{$b)7bz6ArTH)cHau1Jo zA_JJOhvK9hV^iX-S~dT=7VrmiEj`AV{3rkXf&<5Imp5$TzwM^lIvz)9;7g4+aZPpe z7gQw|bRpq$7(m85PvF0YvkSm3!q0B!{P>II78c)a#j@g+@#6zE0G}B?@D~br<&kkf zT(5Z5I|^fcxetKl#^VYY>)5yXt6dFj*D9o7Z`E%S9g1nT=m@q3>)__~@#{NDZvmXE zu+qT{VW5rk-}A&iyig&bO=gyTQcYDaY_(`_CiPCpO_oWhGW3Wcf6?%|fk_T`f z^*DS6xH?{Y-Ic(@{dY1CM@@@`%2DmLv|5$f0Ey<@jp6FWU!G}LgiGypc z#95x_fOU#`XA29*OV)sIivp0z!_%vXGe+9B6ZBO99IEly`CkK_Lb`mU4Rx1LfQ{yDSfD7jCq<0Wu;{!Bb7- z|NW7Su^p9Rr*10bJ@+Kf$~V&AmAO4d0br&)d5@%$>kX5gMxVS+`Io|W;Qo&MgWdAS z{(B4So+sy-q|vA~5@p9=?fBSeBJI&0i-?Z%+j#YECbJi?{gX z&4qz}{Kh+ZDDgiSt;6CN9AWaPo8H9y;UM1p(I0LAvg4=E3F0LENCUZ7!pNVqyN_Vc~d31#al+ZXSJ||ni4P902rtK`AomQec!}+Y2xwINM0BV zOWT!Fr#4{Uz!j%f5>oQL3?PI3m;k1Cf_$4WmdF|}@*PgoyNku?7`ycK3VtneynlOvRqUX{i*W zJ|`o9dR-FdIDafW?ZveK-X9rrVJ^sp4uH0tE@z!CY?p8@OSoojaKd+=!^=$oCpB+a z%|&I;sJVQ6BF(1}$yg#FO@X5MEeWSmEWVQgSomdq8NUAVQ62X#d(TaYgIlR&Vctjo zoE+1h=w-45@`V~etL~5KHDI&c=O~g#zHR?18|pBs3>8YZxngo5zPeOmTOIESL4ULm zR8o^EQDmkKZL;PGe?&B@Rc z;4M7?wIWfApK>s0DuUOaV!qj9`iCnJ#0S9coBx3fd+P(i4udD(jrnUvt|i|tweiiQj)3Vt z2nOJ*w+q)C5&3g7FFE{J&sm(!o%19J25<}b`IG0_JT~C$SRf@_jjK@L3B7^ct4hp7m73cF7>tjgmM-Qj*5ZvP1=0B!)%UL@Fy+jIVRpJg$q zU#F^RC7|riOo^#HP3`kKLIbEncjwWRX(f<`NzEaePopLa)5EFp&lOzXT^W&QNrVCK z6?exGWT*2~lIw&BBrhR*ikhDa!+FEbe}A>c<}foC8^+u{0o`B#7l3aFB$G)LZ{Zl? z_Z7mgSjqzEN5z`qb;2<}!4Z-|Zc+h)0g(T9@8Pl_N5=c`xR0uQd+f?V#KAt<7=J>8DUvWx8TjM<3l`}G+D!}jo43z->{f6DrGm5}* zI6dPuTLf=&Mf)WifWtknjI??3JM6u*h6XSYEXsNxocrNK>5C7Tq}0sLzf<+u6+6KI zs75p@Zu5-|AE=`#R*q?AnzmL;ABmD2?(-DB(_w3j-rj`$y z18o<8s{J6@q9g3c``1YhWd4PM1c{?$nTydWG9c>o-IE+9DlRVQ4yj+iSirha7D zUp9N0dvVGLWc}iwU;upW^F?wZBgdB|f{--vy{OoBDekF8h9oS!D0?wlxE}3>g~PqI z?`HsIbJFYWxOjHjzMT~S4!nJ~&zRFe0lCvUVdRDx8o(g1M>jswVBopUrA>4dFI4QL z3~E8l@%29E2tR`XRM5XnbD1%`cdyTJ1NuRE^Ad`4Io!Z&+HT@n%mD9Y0DkZI<-uoq z(*Tw_kKmNfr`RGp9nLzX1<%3(=j!A6?}pcTP&4B0hhb{GEA12w7Z+OO06@#w=&>&B zxPJktULc?|MbKrvGK3GnkIG*7U0iw*NVe)J{PV&0rc)SBzzT4zOAenJqaoQvQI~e# zm^TJJF#q*pZ5@A`0dV#z-e{=dO`!n)W<7F=*VsIXee*xRBL=Up^!NAj0QNg;0k7yP zNJ*A(-HF@<2XPliwMD}LoK=V_p2=coyGi`J|B^8*A17$!t;b+E2;(S@1zYQaFz7PF zBH662ln8`JHi5m#pGK0$#n6ze!89CG7lfZUx&1sL1pQy0gKPQ#{N@~DLIY zKuf)sGH{{rpAYR$>8dmF^1{A|0(jRe8c&MhA@jG!j*;%Q9dxt>NIwQR{mD4JEjXit zYWO`-1wS^R^A*PrlTx1(m&lZ#%rS?;R^rlrgK#%`pA)d%;b6YyJErEkgsSpRfNT!R6)#~K+-KV|>4?5O3A+EjYqav-g}&ig=-cg|)fXQdTa9k+6_Vh@O@+>iJG_<}W`3(Ynw;{gDLNQW(_k^>BQ^-DbBJrht_K6x;Z7z^tdb)E%rCNFj(} zv#y6758~kK*jW$-3Dx}m;d`qIK!t!~PZ^Vez!UmYlio^J+%g7yO zQGXaMch>^2Tjkk(pRuVGt@KP`^KS^!PVI7CEZ>&jtnI-S?VSDC7^DGEwokbkYv|gH z+BPX@4P{E!916tkYDeAjTl~QM#}mrKvP!z8fbUpqYvPrVmz=D(OY!ki$tN-I?TvY7 z<=Q}gDLB{GZWc%9<>8oWz_OE?luR;@PZSF$e31{U2 z@L=n1N588(og_KQ*e9re*|?|EQi1vPZ6yD1udE+DUSqjsQ5b2x2E48un8#&L@iCHZ z^FZjK7~t^~4Zc28AHyds&wpW&&FlKmPI@|%A}O^Eiu`;{Hv%_k03Nh&_G!{UYM1u9 zaODUCz1%C;xqJvi4h((^R$PE*r55c@K##sN5t_t+S5Yy58&gp-Tg0Wge*_SYrPtPX zR2DUnsi;C9;B*3SPe zhz9pJ2VfN{%Kym9%vSOjlSK-<`xge^qyunq@_Fc6^E)k!#`jP^7WY0=XtL+ld0<2N z;i^H=0rLAKnYF+DDlM!8xbDMA-uFVUY5-ipW|kx3K{!g9oB!cW!p3jPC_iKNIs0kt zTxM&feyeYr4(Ti-5v}aA0V>>Oxx(i%cQ|tT);kzI#=`el$ac9 z;wMBaPp~b#KAP<&j|J&{K>n-ns}Bl0%9p6TXwrslcK{6axrHDEh3V;<~c ze*DM*#9{Za_akkQk4vN4z~cyq{Ex>|<2ZN|^52Q$#IyIY-^UyY@Hzwddm0VpE8h$h zvL+6|OP+Uzav1uXZvl7%hp>o)MHzJ5Jeac}_RB^fDTg(Oh= zjDiD&+oQY48o=oEKUPLNZh3=An#fq9o^5*h7mJuCa(ZwU9%9+fI>EXffJ8Bd}OpKs!P z7|`=9i1Hl#d9xG$tbk3zs~rd~U^S%;Pn_l?)nRdB*mM z$K^hUEs!zWI^=g{p(3PI)eywSwe+A8F~h2CAaYUzoV0`3Z}b*PEWdKQ=(EQ|#mg`` zo3sSH4{dlO{ZcnI7M0;R?%{cfwyQBaY&66u-c2X~g_RHD?=(AnKBllM_46<j5kk<&wycu@7kkuoBW?pX3HCKW^*dKH$*;dbVci5Vx1UsI9`HQEis18lZwY9w~5d;`2J9t?8 zU<w`J6) z?%}Mm>@o{K`Oe-kSiryFudqw590_KEzCM5#*8VtBS@tfr7r@lQ!3>j*aS}W$wrybm z@*UBA7+QN#tT2lHG5^#lI*LL5w=NhCz*Fq;a#|RGe|`EMx~Ju5bI0hTozmMf<<+~u zTAmZ9T08jNgg2#a^ngq}Bdf=$59B7~A*G=I<-Gx(ByA~3pz`i-Lr}~ym>hsLN>!Nu zuk{9)|Ff(DaLiz6X1IQOlvP_3H9DNG%J!-)!0R)thfmGb69YIJDS7YnU!P3?&ljaq zM98cT@WqK0!13PFRWEhn;~Ll3({b@rE!-uO6uk7f9cAn$$`x0h<;9%lp}{1g3^}|T z*sFLH3+IGymvP9COK<(o1n?M~j*W5_v&IXel0SMlJrjYfIGcDitPWWxuTpJztgV4( z-{9wO{7By%+~n@3ZR|2h-@aHu(4-f21&ag!J>OrOWOq);F$3UQID|vS#phUU0N1dF zcbN5I2rz&f`S-vc%l!cUy_9!*V8VH2>x*O4>_oOUcyT>{10S+eWjo3oC;DoQvW zqO0&R$ymW9{1bf7zfd?RVY{a&)SJ$U?dImcNV8SGC0zP0M6ycU zW81pXn*mq||2+^GA#xYZNZaq0q<~xYgb!^!J=xKlPrJqGh$*KSfGN?6a=tqKj5CaZ zb!|@!vY)34cxk8Trw(lmb{9vDKKM8~J5fV;r~-UNvM`?W%W}@qz?Iyot$Lx$!i%?t_QqOQ_r9ZI~qEel!cPgW13{X2}a12uP{%j~C;&jEDkc zCPe`2d;XlDRhgCApOXS(}jR$(5N=^fz#xwoPys+RH46M%iBzP(HUidwyCF$m)K7?0#J z9E`W;4VQm9FIFvak*!t`zjGf#_>2ACBtiep-Wor))THl1xDCzD;6ukm^5u+o@&AYV-i?6lRqzsYf)riInF{v0oA zO#q4}!E<&bfYEL@oN%PeYefk;FvzfmDQq=bm0w(P z<(1`>6I;1e^zto+AWc-45Z(>}CVH#jOgIE@#JhM_h7j#m_jbuQ%@Sf>9^m*}Zc~2*3eiyEFYq#Cc4n?v|1?m123| zUnEO~f=)17Ka0p9$wp4#*lncL#q3uAyRg9gn5|mxp}6z@-~T+Q6J-}KzJmt@@cA2( zYc+55ey0Nu^xS49aEW#}69wSf$o%#s{^0`5u+ak8@qsZGbagtw7Xcr_fMhFWWO2M< z)k`_E{P-2!FqsnkN|Hw$x@+ab{Yw5J3`jP!L~5e|{C$P_@BJV6IQ=SoNT$SC3rte# zLjS=C=;deKiu>)ZeIe6~FVaj1kY>e#3-s^dZTRaJoQ(;5TcbzDs`O3&J-(Q=yfmQ+ zc+C&%=)E)Xk@7K48EA?KY!{3}i$_ir0)~04Gl@Td!%uig3-HiYO-fwJ0;TSU&;z75 z10eYkEi4c^#ac3Hs%RMo;SiwG4zR+FZ;exd>ICMf8LVTHTa|dg9aA_Uat@J$k6Y#`Ql-SC zGGg2r`w8RUL`}@!ubYEM2;~k1=qJ$Q7%Hkb=hjV~qPsbNXFH*Y@8hUa1J9=R6>yLv zh9hAX9ITfmTH5|)-X{L2`b33Jz!l=RHnyBW5*f4bDo+b2+w9wY7P{p#$C>K+jSv!7 zHlJi`5Z49;6L(((2iUEgM_Rx(H$#~(IDmH=c_FzuQ|Tjv(gLI22CPQj^;WjvV!ISTvW~6$(bV%hAF!qAou9c;0H4Znwv(hhLveQrH6pzE zWZF+u(w5f+uAF!_ZO;hUhW2?WgDX}A2V_#uRMfqbD9IB}WD^708sU%o0{y=XfUX|o ziYK}(tp~_~*PrAm%ErQGTc%CCY7Sx><5eYnMDVqU{D!^DZK46<4r{{?-{}3csY(FWcfqiQr zZlWKG#^%|^0LmU&Ua>t93BV%td+l5SYpZ`HzpwB%%PFL>$5t_bfZzu1kA^s42mbki zvKNs2%)SbLqZ;w%zICK+Ni++Hc4JuhV(koJA5xC6&0=e|J?PnfgJ?UP@Jq{jODuua z+s62milpr#tz}kFsPuR}k%sqg|EWx){7w4d1Hs@Ir(tFk(x7_;{5OXE1q4*#10;nC z+SS#JOg|3ESD64D+5ueE)XlfQ*KZIU0Mow1k4^jPayXL_9bcCRK-Dr*Y9qnE58V5W zg=j@Vi(9_6P1v2@e;%R>Z>xBI{gv{q0FK@AoMjGp716lCqb$3lP2a=-n9!5?`Dq++ z*w`^GNX|JPDQIwDgwRJ;C2!-^p)ZUuf8|>}ivi@FZzfj?#J_5qki3uql%=v4EB}0x zhcA5ptW%gzS?f13V7js@1L(~1NVX>M_(rFHSOFw!ljj&bsGet#dNgL&&IsCi=lbRP z@x6*~{`BIAUx4Yz+;hGt^vi(pWjQfrYTicr`!RFdU&-YS@I2x(i?Pe+uP`MB(YgGV z6VOW+{`nl1)!ZkDa?IMD`2Curp>_;H+KksL0wQBN5f)v9^FN>6o_Im z*sk~TD->baw7aIn1M3e0{6~qS@nMV@UVkN>!@#98wSTUf047?K_Bb;b3jW|H(tiNC zmuM4_d-rK4LK*_TJQ1j@6!uZ70n)vf`Xd6sl3bnpWeCeQyW09q(E($3zkWU>7!dSNwfM!9 zWE5=}r(6up1K^vS#`8)TKjhYncA(sA`?LPjy)$uOyB{T}P$^yo0jxf{&;T50xN%KI z<4}(@|2}&cqu&=DDvGjwJ8RQgBipbx%e64k)|Jva2 zy)}u*)r$Ou2@Ie=NDDvVG2XoZDVTYU;;y%(a#@8DCz=2ZLyxw-@ku-&OoCdBaz4`K zfkqU7J}H6L3jt2ul`YQM5RmswuBve3?eBbtN8w4<={$+A=m}_^C+vbp9|9v)y< zn^h}$sgB2FgMcz#RX&Wr%iFD1N|AERSo+_%PfwpClMP@bwcpfb~_AL?qo3-TmJ&Zr; zN2Vg4Lpjm5h7_S|-WO8_7{&jlgjLI!_lvvH49ChMS^trl0eBFrV{xf$bOu?5XS>MvFO| zd&oz31(k6uNUlu}cPxwo{YwW1K;!aSr6=ZlD0!OZ+X*4>k1Bo{PvP~(2ctuN`x~*N zQvh%G0nm%#QneR;atP3wX$N$dnv=CJ`sW~9Ld5X|?5$3~@+|9gy=tq=@|E>I#qm5N z;8w++ZjUu3Zu3oWv0j=d)&f{RdK+TAv-xTO;})I@`BL?EhtnK(j0|Gcg>_MY8aB*u z0;><`FtO`f0Aro{miCuHv!O~Yu{0Ad^i1J$&qOY30Q7k(oe+wz&tpAVA3*zV;0#{n z;1=H4=m;D|dRv2O)^=^af*YfFM3it^0FGsb&Hb7Xu9+XW4cIG3-YiYWiUjq~h@0Dy zn3z#&&PBVOjX;ImdcgK)4vhOnx_LCwTCMi8p(3taKJ~^7c~I;?1gkfT>mk zVD?~_83ixa0JxW#WT2}yYya5g(XdZ zGJli-R=~_yB=t6Gfc0C-Ec4uk5l~<_&xfsMe%PUg)bf&2y*>FkTvZMU_tM3Io8Acw zklrMJ(FsVyb!!Jh190XNV;fK95nd0R!~nR-UXw@DbO6(6h9aub4^wT&R~yK=c@|{` zz<9lp-H+WgXW9~3Ej=c<6FW_o`SbBJQaLa?Osa>~ZU@K!V{=P0!3n1altH4HxVH;~ zzOUu$3x;OhlPn069m%eoV767Px{V`euy8VO#4z3z;0J920TgHA7y@EfJa|) z2F-X~Hc7eGA1APwdJeFW0{&tRb$ArOoJa%fr$f!>0HZVjQ(_&-L<_=lHgh86zqmd@ z<^l6I4p2Y2WlaF4J)i639^l{Bs+^Pu{6fVY&omjg*ByUuolG0r*(P*;d}RHxDN#Ei z23tK02~cn8*+5Udh?7hss(!4Ic-*QZdi5r11e_FUmp4GC%oTqYbZCi-Hlfx3=ty^zO zG~7eYr112^Ss@b0NE3j`s^t2IvwWj4c=Ozmc7U z0Z!7OFv(~(QeWA`lxF8RhXM2#*Q|@??Bc<@8G7$5!h&M(4V-dQ;m}k#oMCcrnS!g? zllilxAA(S2)$R+l$%v3sv$J~~l6Se@o)#EMMMX<|lE&@~H3C;OK_PeZ> zK`GsfKZO&1y|9`E7+TO*N>{DJ&; zzN|oqe`XB8CcaVr%~Lq;&^B2zJ{@a2J{OA`RNy{_&Uk5`M?_c-uTy+Hk7*t-9L`$- z*qt)y*biZA-cbA*nP>z7-?r0O@iU)zfQ)09l9FRnBDQu>!2QQQQ9@S6&_DpsGW*LU zO?h%2Av&hPU=JTcISRm=Fw0PN1G?-i=kAg5nu*lC9M6tyd(*ksh7mj%c>YKzC;yoe zoWUqun^;WT9|n}y;b|xYcx4SR4ozI$;kk7kv2T__0ZgVSCXuWuF{y9~k4J$W1oHMW z1a%Y^{xtX|hF$jYu>e2Crf1-^Oh8^LqykuvZJH8QSJg{rl2eQv%>N}CHbib^04y#v z^X}KFXaP((o`a#DDJii7TK$b3qwEaP*|tzVXF)4=TMn4kmT((A$JZBI6E#zIfI38aR| zpJ-f8HN`VOY*AS#^H^~UFwF3yLy@hguVT(lNRb2lm)-!t81uyvLgv@&{`vr(^I8VF zmF=TQs;6f{ewlY^01P*psko|6B$F%?`s4KfK7t4548I`+O|oL=_;Y(l=X5R_PGCnj zBIOIeea(F)fZUn}m>C~dG8BACFwij_WLPIHoNL!`=4LE%qdk}L+=#r%eTIMkHt{4M zfGJUNLH@|Pz+3j11l!{Kuln!Vf?_n z*jqAVAIV4evtv2rh(e6s>*q)U6u8Jx9mERnpetYbC6C-OJUukJ>d zKmZ2}31B1MLW1Yz&qSV1-hBgk;QWdVd0Uw!0KnD`2Lu6V;3Z;80j>lt1#bgKUq`G1 zKD?5G&F|N`Abg^!k@1!i0KhvidUoRj06(8y)C9QFyp8w(`0~#+6e;_Q~UkPWS=2x2h6 z|MRs|jv4|y`78jb{Yb%Eh+w|7NMFMzLPHF|%n`uqbpV0~1#d0E{TSes_=Ol!Rc!tr zN`_5$Y(wV2(ap^87BhPWVDDjoOL!asg)4xt`g*1z|KvJvAD`5mEFvy|2w+hOum)@a zHcQshW+eq<`o}&K? z$oE`;a#|oIBEoXb+snBEel^>MZ7L)Wc!n@mk|20HNCE6m=q(Ps1Bu+{u@jaXs{koD zM)Ee2aX&oyz#{k z426G>QsS2Thm2TKYWakl`l zt|pJeU}ax$!7E=aw)n3oW-(TgtEK=cLgOX8ZJ5nS!~i!(oh@*LBxE8!npOA$?6Ywp zL-Kzb1$|u*+w|=cKu6-l2-e>banxvLNsU|HHY7m61w>t=z)RpZx|O^g9D^>$&O>2T z+S3J=wRPSO6aYp;DEZKK794qfS+bC~np^`ghZsQor0VP&INHQ}+qxb+?JLl5?1R5? zul0#sR=gjRKzyR9~0cJepZPdVbXaG-( zU(&)r*6yVJRY%rJ-63DhO-AHHTLXCgLvKP$SHJ;#mq1 zy8?v3bCw)+*yV7cxC8681W}B~bNIBsX|7Z`Wdj!YfXvY3OAwuLcgTb$fdjy5%?34OX@))xkZVldvP*wUt@90&mOXr>1OSV&3)X;a z&Lz1*YC70B^ZqbllyUEQcE%s;gIvc{_yoW#5NrVg{#HobmVS$Gh^x;7@SYI9JH){! z1bF2YVoEM>5gFeYYbh+WKKqVi_?`@AJ(f_>%~=cp`JJcgA&{|$;>h!xcHjUT0D#s2 zJFMgKst*8yE`Ey%T(QK{ho`j=OrklldVP1Zw zyCd>w=)vDH(P;lFB(PTSc%cnTqyRYARcQKkIyj=2kWsEn71IQNpo!BeL4pK(kVl3R z?4d;!@`u{Fb3SONE>Mj=Nf*7 ze)NGQr_DJU%``IB77-@KL2}M(fPoLu!~0{)4tR87Fia!Yf&!JW){2S^#IQ>b+u4&o zGZjq_Ph*Zi=K8%{aR^n~J*J%BB)FHsq5DuT8E3O0vFTFeL%%s}+w zW8dR_95_jv0$7F6=&=HpqSsqIdju3%2AFvXaP_fI^VN5Dw7^DhD=q*o3mzaL?v7oJ z4_MGWE+eQW6W$uOCrhS)wRRQ>eMN#pt zF_R@;;@)=ERkGe6$Cv{+E5>h1kjarc&uMn0!RStBBn((BfbRE`6^|-A9;MK;CS!gcIkwy%1p+Z8=K}I0r4pQa(um4CcX!nAP-vE za?b#_EWYm_o$)#y{AM(J^2Jupau#E6px|XR6v^k<9P(I#ielXnz%T#(u9WujaSVz8 z4Zt@8YljD@E^;HCxkT%bGU^D=phF_03 z0$xL}V<7N_u>gBp3=;woB9??0bWMPTh66(O``p+)0|2Ke;Buh>`v8d#;ThknsqpC| z0Jedv&MwebjAPhfrWXM02n`aVQ~Vd1!rC^Mzz!5}&=6n_!0}ACvo&Y+ZV?1O2mn87 z5C~unii~kYOvdah3NDD*a0TE}1FvjBEBf4mSObvjYrZz8LdVI>0ObC(ylPHxPy8YP zx*@=OV4ol+p~)6p0Njva_njG;N}N>e7#?Uma}T!JGHp{V%n`)B^S^);ZdrU+m2`;G zccuWy$4tTSua_R_HCKQmV2uOVqs``h03R0GMu*E$b;CA3#0Kzm!*q5Maj8iq-qVHO zJu_;P)jUGDjP1et=H0N6*gXXT&61G90JI~7Ex1yFfIUxk2%v|pc>Y~Zsw#hs_B=@X zR|~HXaan_dGcfD;v<0w~oHd`O;D!u`(hL69)M_WI5#>X!X$v4I>C}VIafr(apva2W zvgSHD0E9j@#1WXH?XV>yy;5H6 z4#JlJh}URW(d=*B?ocPyx@C$s)1C_RGzM+jT1aT95IoS8M9LLFA!6zT55>}KTh(1O zuuy1BkFsY3RUbb-0GZEYrH}k{ov2%Z$u*BTGe7k?!t-73}Q$-b9cA!F|PiCC1(L3 zK~UuGE}QiCb(vzw9{~xKM%vzZ^EnWFkUa>1ws!p`Xb7v9__sbO1|k!4>Ie{oyiN*0 z<~K571u&4O%jhN0C>oDi5El?#@U4yjVUXAJBL5+x;$kq$1S~G5)?ksdgY|#>ERX;p zvsOGHsyg`Tgz&465={@sO{Z)$`!~Qk5HC5W|+uBHn`eN|J)TIX(xe8wqu14 zw;7&>joQbmO&|YC@mfMUt!&L|IOt!*6Td@99S^o8O(c*9SNa;jYHl81sar~{(Dd`n z3@#`J1PvY8`!SJ664+`ql-MB2fPzp1mMI)^5&z$fLgDxp&DvGfG}p_M*&geGbenhk^blLu87u-|ivoz)ak?P#f#}#VRfF1=1Xt6}xNjXNF;XhBzoFxd$MA84VD9 zg>8hh#ltb@HxD$37}#cn{l%kn#sJdsM*ANz2n`&`4Woqt!dg|WNLT~=->n-;JjOUA zz|c)j>N3JFCOG#NtJB3Dcx0mYi?oIwRZy7Y;cP$^YrkZ`XifT!UU zE*IMB_QqHLoi6?ifDu- z=qA>{A5!C$Z%Y9MB>UoA#2^9WF@O!=EBDC&upf>*%|xzI-EQHvbw7p6wOTeI10u_& zSz8M!ks9E74?YW*B*1enm`+YN_war%)>%C~DH32F?tQ0agYCwu+4VEv*olEg{ZSt2 zIO+?|KB|D@c&V|6RV?n$01t=(UzD|8n^^7a?HXq@J>Svv@+~>}hqWdFUI0j83k^Vw z)&NM!G4L8d!450nnIAc#A49N>IaO6aX745V1Tjz)rRGRKKj0I(GwV2}3p)h#a}fi| zkAR$81CU3^|33iP1&RPb1|IeZMEv8VtcVwH#yMSR*aB}J0bKcNs~j^THo##D_m~67 zu#7|l5}vQJwZlK|FWuAN8?tl@fX#SqzX~}Mc*GKU0GD?@V<$!YBz^n?2*^T!Ict^s zxdzTaR(2rn{`Gr|Py|HuQ*cu*Rfah4Xu%@%QB)PNVAa!S3K#1$LS_|x+`g$Jd|Sps zU#ms~w_ls(pymJ)(0AEIiTEXqAJU72`F`0`h_Id&vp*zry|iJr*WC=WC(nW+rVk%9 zALXz)zE3Rxo(@|^)YGiO`m;}lo}rfw_^V)?+*O7EMFJrKF(BbNcfx8$xFM<*HqgsJ z@&uj(YZyR6%-!(fhs4o9-N5G-Pa=S=0tys>g#+^NuRJD+h0=f|SB?u>1v!{9`>Itu z2k>oGmY@mYCOFWg-;sT~HfM}Od?E_^nE@AA4~<+Vz5?+5EzQ^YeE=UrC!371h=zBA z%6kBw)|khj8zC#c{`&y(ndXjcj7?!B#sH`&UTUGi2f!kU0DQ$=2^l67=0g!E*fjvE zZtKb{R{x}NZj@`6Ey05L*0vWTbVB}z+pS412$#!t4EGZQ4FR7mcKcuin6X>yU$ z$C=d-k(9laL5hHkDE_)?nBtAQ*?@od!h6^0;kAe(5=hxxj>-%)1>q&9xB`TmtVkSj zY!&2Dk5ztO2;4vhx)u&7tPZkS(hwjDS&e+pa4rFoBLL!PL4&jU3j7ux!2>c z2Ac}aN<@@geG)i%_F{6VX^|gc6$w30rHef3cVCyD=)}c4WC?{ zfOuVRm(mLjzwBS00S74{qxy?4x10xn<~HRQsxG*|rrZTlM33LlyTGo7#|7Mb&j*2n z4B#dPjzDDqCVb{;U=29hu!pkhf?V<15t@}qmc>N>1mHkjeGwZTeBUcN1bl$JUR>mz z1;Pav0hcLX0zjSs@g;X8Oz9&qB!Q-4^AYiKR4(obRa3&4yKzu# z4W^4@MMdC~u%tjYmTvc1m6_0T@YsB<>ia%s8nRX_CjkV2VpX;nB(XUTlGIIwU&cXv0TMI-YiQKm5#S+jH5!-WgD;874x}L3Ty)sI01{NLH0jw!64#y zgk}&QOT3I&V4=(#;&q+>zt)EXf1M6q2>4 z-xBt?8^6bymJA?p@%Jm6pMse_HJj5xu9DR1v2r$3%K&;O7%yIEG-Ovqg431&8||_n zFX_pieXr&zLqzD;oGS@DZKG2BkZsrl2?=i(x;da8LC9gH#p@uQyKDACTC8u9F>JKp3lZJyL=+=i zkW)bR2NV8;wE3YgVtUv~B(pvXok?H;H?9EtOP3T(JQR$B-Xip`Z1J>rBXA)!0EKJ} z{m)$~K-grwzCBmNTaCTU%xQ2H@k|>ZY-x>30XCCu*nqh(z(WX|QAJD_{(zXje6Vzb zs!HBgju{dndLrOnUK~s8zQN$8Bi5vkQYXD9W>sB#ao4Ph202}l;rJakW zJIQtQtZa+z#)V2}7jO+E*GS;HWkw=8kb_a3O{ONjcc|`eNUp3pP0n1i{v&jh-my0J>}}d;SPW zw-#TleKQMrLq-qfzyWS1~P;rn%VFU|y2o z6=6C{DG|Ck?q&Bdl;UN$yl+d}^1M1xH%M+FBf4njQ~r$xQWO9N5E2lthoBKzO^7$B z@R7Y2HhAXey4svr)WyEATeS&71Y8o6)(V>s%Ic&8JY9Ez*DX$b|&h)ECkX zbqbg{FLdPJ0grEdoz3gFowf<0F2$pqq#-TxK!w z8n8}2$HBC+L28eg1gj{}+blGIVg_eNINUIqT>}>I4A-s_oHvUIh^mv>^y8TSRaXJ6 zX32s}xyr3V_t+)?BJ87C%R7gFC97PLWXaE#3Xt9n;vd>r%@oZCq38$z#K6Bq;u97}4%>xkjj+#w7$EA;K==R|L>vyUpnre{F+^1tgcQ-LOEUbl7*HmY|Ev6$%WZJRC2O|H|OnP)w6=9qD&+7*WD+mCh>Q1`YNrli<<9 zlEs5Mw95b~XA3Q*)7lB0ys3e8I`ET;EAMl>5SI)CPEh*t9q#i}!)f8Ou{xw=d9|D( zf5p(`6o8E*6d^4H9Py2j%1TAPp7xAsO-w`=0>vO{cr?7~lSu#{1bF~@PA5L}nWAA9 zlw?NHAOQ-woI_mzI-mc? zAOqiisjpN(ATPVO(^wz{Y|CG@>pJ~rgT}y2BLOZU5N5Eb#_-Rg&agWGM104)p#zWr zF@(LFEaz}z`r0_40Qi#qY4?H5&w2DG}{ zj-EthK%mJf`6UrznrSRsTN!>{{!Lw1oql_+=~jXx^g6(mp@S43@C_wb;s;2de7x0S z5fbREC39S@h*#U$mk|T<)M{Nd)=siGovwN2 z1IUnygHzhb2^-z#M0xL?RJ8?=f&xIWTVGs{Jw2>Rn=%IA+tX-Zk^H*4uf4}#`e}Lb zXC8mu{yG4!0TB-?gRs$V*WG0sC8|5Jxd)IS=;Ia~(Ir0n*#oPw!-gmWh!Po8i+Eia zAVZ~e^EkE|a)2Vi*0Mtfpc+X|(XM|`NG2iq_6<7FI~+r%;Og-{1-f2Z{w#(2V-tDl z<6tA|cp2ay_qU{o4}ep^TOex!Y;8b@9gQ5Mta>sRa81Wxo#{WJk6jIE#u@0&V@z*` zlDM1Nxzj4!?1>`x!DE1p0zCbLEzvT>&n6?YT&b$#7ShlPg~K{Pq}hY(u@u<{5pF*} z%%hB`*QIO#78zHazZrkE+X$P4VH6Pnxg}=FOec7C1q_*Q(wTfkO1s$0&?}z-YBCaFdiV>&jn>S1@%a)e4A)3tN-d1y~GgqZM|*Wn`@y%39L3- zK;+J{5>bF$s#7w&@)M1m(iwt`oBb>p;sy*KA5y~`{wP6Hd_5{0#o-n;I9wTp>| zfkfqcuBh}=DJq4g5Kx)JQSqi5!iI-C)=L5%F3yK=Ggg<|@F z!L#OgF}jMbB`(&l{q0vGx|uPRhX6V?)CiTTlvB{)X@X=NF)>}8^jCQVbYfB@OntHj z<~_r&y5=k1?1-MMgSQb(7wA z1Q<8mBH8a51)@9h{tL39G()yKU4W#=V<)({`Km;|W9UBOBGi&Go-@1qUR*nTlApv# zR>8+GOh&)G^ge575X6#kVt`o+ATEJ|enK~}dl7&5sIyDSI17N_Gy!C_4m0N)XWd^& zMiDcsAly4Q1jGQdj&MOO9WZ@d(n2B`MQ#CTOc|UP0lfr1bxb`29CAYo$rKdUUM*uL zIoC`j%c?X;kR~(`(*)2UG#J8nX^4b|2RzYE+@ydE{FMsc(s~PQBn(mLbth7`lMa#I zC7>eM!o`^vge&az{+~1xd8uxl3Llp|LOLm(ZeCw*W>Q6&E>JYk-8S!VSmDmAzpatb zO@6>5@{AC420P{b5dV;IwirV;+xH%AytL`)cKZ7)0q{u27ye^MfZ)1s{&D^+3d;Ob z3I{kuos+eQtW-!Ec!!yImsvofpHb}d90YXBo z;dLTz|APkSVzHwIHLP$1;Q8>%C1TCE)j&VmStb#4q2W1T)pg3oO@9EZ0A$KE*7~pg zN~sX!)ljmBK+v1=IGdyckBFB`nt^2>01`_@U*!i!I(tFW%hlw7q}5FYko82uSzV-D z{rys+9^}{_Dy(YzIf>vex@wSN4vF&+J-k<5o-s`Joa1c(pZPpSNr2-m_@!C1qO$!N+p6^-LVBiAOL^qRy4Yb9V}!NX8LC9)dkqCJHm`M`9O>~FGane10fkl z0jxm`K-zRrMO`e}vbr}35CZXNcFWTPC6Pp!o8DM7A|BlgwZ}I!3KG!Cvg2dAxe%R& z(Ju2<1;_<}vQbRQcK{&1MBu(?++$D^$TqqbM67f_+riN`S6;&u zN6lB=yi*qleOYPvb+KsHJ0}#*7-%ja#*&gF4S-0e3Xu7&2;6G-Hp~QgqkCHVFMDTF z{zL&T+;{Rm6_Idw>Z)|e#;}T;uzzHTHEHz@Mc0ARtJq0ukMCq5I z`tZ;$xwcVw0RbR31+_zwBlex23HK%n;N}w4vNM9(!gJVNSorvf z(DV@mck+ghzyM&sXq*n;;K=E$EKwYkfp^#?q(5DN3mlFB3c{EYJx3%s6wNw|pqUNv z?$QFHHnTj4DEVm(n-3imZ9k|8tgbZ2=d_W%({~U+cE?Hgykw7zCVtaZfL@AsQe3HL3a(V+ zB7Yx;_rz|hXLTL$yXK=-+Y8_XlDMX>_(|mUw!ap(hCnz~0PAE&9K=sPkGfW4gX0fL zCnlFIox)CT0YifrUd}auBnHSK%&Mh1;KnM)1_~U`_i6ADv+)9+vA}4I=T0s3Y1wAfRb9|37!g zkgQ8*g0QK)7=R6Ob;RB?wcAU4zpXIubRV2A+NEO5D|>B8O%d|m-YuPi`N zeQH*}Pz+v^bdyBQRZ2|{5@w801gbvHA}-7KbV<`?hPsuM5Wpt@PN#OkHEnL^!T=mM zzbsmDEWj@}lvryZQ*8kfhS5=6Z%B2nTT^gdw{#hE08UsGH9K(C4%TNjmT=2dQahMV zM!SX6^%?nVw98X1wVz9YT)Zlz8=D_MEQn zs!$A^u=gSXF9sb`B6K;=5866#G=82^wG@n4P-3GVjXq}60LKwaj!(LR^BW}N1gh=} zBv4<-HtqZH{JE!biIc8zcb+3xnMN3d!M|jQ=sqPO*!)@Y2rjo+qI6fK0nUIwPd2d&alW5{Nqs2{gFsopl$T&gAHUVzU{auD3ym z%a4~GYrnK;y78ZHXA25+OL0%f0`s+@T~}GxaS%^wkX1|A2TcJ&GkO6;ov0BA<~TTS znJ|`aop)ZedQlf(v1qiT=@Hb*xcq)Or~Y$Ii5GPSs)6LOJz#)+>V%-^K!AO*nw=*! zDP&KgM4}1lBBRGq>MmQMM@-1R=7kJQ9Oq5D; z9ZbHDBo7gVe*iQ4>jM|p1VeT;qRy=h1{aLN#u$y^<{|7F*lt><%WPmiq?M-27F)T; zH4{l7WG&GU0iJ=NZZ8&Tvj-|iD~MIM1Ch$qWttCV?0%>6IScVUI0Us9_ZZ@#tFV%f zjUIb0RK07@frWw#Ae^3#yQG`$i0BBAmD7(YNeEuU)2BfGcl+uYwsJ*_#rLJ1i%HVb zN8~hxhCPS~U$$RTE8i3^WnU6o8aNucEF%0L>IRo3VNI!h5U*=WHb1X%5Ub}0iqh#5 zt(7ws2?V05#*3CM>cR79UiQ;w!Zy>8AEJ&(`ex?Eo7gL2o`-xzfk@zUj+yed2>=kU zW-DBUC$+dT!#ZF~Wh+8}h}QraZ1dBoTI2eq`mb?0zxssUbbsC0?!1kJZ<@3t!M+G6 zT1}hCW`72pehne7 zIq+2wI@dtK1&cXwp4O6O8j*4UXTa53UqQgSGd}-rJ!}E&C7mQ8aKQ#-u#F7>G)S80 z$SMHkm{Ub3Pb6{Th{rI+R;Z$mk{ji%ktcf_7&prB?XByk+vD z{tcH20MbUIyO~o{mH?md#V{|wzE28hunRV*kc%pl=Y-;gmjJ#S@k`M>J!X!JFj=k5 z!t!G6l#{--iIjQgyL`43O7~S#?R2FSC8*k;56-F<+y`PPKtR^CI`c`BZmD3c)FUwi z(WR?!1=h7EqLHP^%Wn10_5tPrGhFhJ8ribL0!J@e?Hc6(@N@wvP07~*P>@v}1hB>T z9}U>{3wfsx_N|kjx>Wor%b;oleyX>t~x65wd!NK%H`ea=J&NWbM(?r1Tm)J}7yxUzd%Dh&j3m-)ATlIbBgj*UG$XiNIA8SM!!FAsSb)dh4+fv-MN=&Da=N3@t z*u9Z#jjp`$3>mntP#CiQ^MW@CeG36t&BH_k@R4SCd=-L+p@#%P$=S%g=fb$H7G{8C zW|n(^<93G4l7f#0FeLP15IUSU;Dw&)bF0eCNUI@lrsNHW;6z2iRxUA|U| z#C2HGRhLE_tG*11MYMk}gM|VNAZOZnNR+dGP?XN0KS6TItp0wWLsP!m+{|wO|z(10DFjpP?b4D4O;+t&%Fee_c;xU zrbXtQq$Vkm5p6;?4e+7{Ajqx42M(PbM@4(MoF1P6!0gu0N9JW9=dP3Vsbk-D2toNa zJK+sroB&@}|2l)|TmcY{9ylmJM~$L63Z$M}$TpWxSHv{QQkJB@wNIUZh+dAtu>%I_ zyo?1g(~)1j*YQmAZS>B^$w~S)naiG{N!c>eIdxJ(NgizgJU`a~M2%;Pv{Jc@Eq?7$ zbBUovQT-FkVwofLVgMu;lpa|S5NNop>B(P7aY@L?mPURydLMj24I_V|eboQ9>or8e zElbq8?`9rl4CJ~Ty{Artr#xmDsToM51prUME~QSiQ|)e-n?FkCjxEbT)6iSnJu|XS zoFsyZbVF#y8Cl?I+-GXCwEon6;6XV8Mn2(rE*Dcz!jc5*lHKBwFcwEBS_TjR8T zRp!!<1uMgr9k)QLS)vp*w0!~QfTu%Tl&i~&zOknTCH9HzYM7sK|MJ98C;g1xv__l& zWR1SiEQq(MNTPOann6<%NjmV!0>Bp<4Cxw69&!xwDLlB|?^sUA;OqKg{4z*Y#T&BA zOlk60>NP^|kE>O+OK!zu4ePFQCzL28cu6Igu;cRrcLVbyuM{$d`1gOvvFDkv{Ii3e z#SKprfS{BQf*)$Hrp6;qDya1k+>e?!JnD$|YOtEtz!%^{0!R?1`sL7eY+K3T1j)7| z$)O{xf=CjD0ZR(h1)e6~LABlcOrrn_@he)^ZExIHIWKv?sjYwH8a!VE5!}Xred216 z)%$q>SC1~Lmr3jE(=k_Il|SFEAHjRk7aB>|49Loy2(uOe@+fk9&@j&xp=qml2K(dy z#Aj89Tg3npMH|(9ZC}DBocf2n_KZ_UpIU8ur5x=pC|Hs@3lQu@Zpvy+|GD z@WLQ(J5AF_10LHdi|C@;jwvlJKnB1*kOu(7?Q_r6@}wiU2A-fr)?@1vAzTkUGzv37 zH%q+2<(zZ_3@cGU3Z`Lc;#MSRiIz)*|3Ff*=ToBCuSDW+H0K|>r=NFV0TIBnS9JB) zUcLnHmgS>orY9{!m>!dgux@f~MmM_4>tLz&ZpK=wyu_zD2B7sWfddatUTu@eBY zBN44MP1Im;?8|L>^}~IIi@`U(T)NK?fZL@io;0n@KBja&7G(E4)2|;CxEEDx0KFt| z4j2Mla@C3uuS$U;W+lLn<)801R#NEN+-?ppP?jA3F}F8Acoz%b0(mHt_;KmsU$ zbi5BPz%SMFCXrJD<}Kb@Di0jo$hLmy{(w0hT!^+B77;7)zepYzjV>^)2KJ+gIszmN zMl(Elrel#zmH28+08bBeLBOa`-)=yYtu~mXt4jTZF=K?>4LMEY%xJ3w!13ymv@0m~ z=|Yd6)DgX9Euff0*yFSEy9$sFysaG!uP>?d$KPNJq)a60GHyPgnM~w_WOpWOpHv7~ z#xZdvfW60Rs4k1(!Gg(nB*>;pCrl@0fPx83b;n|bz7Tq)xuTrbXL=}9yrsghQAsm` z_){IZlhc*Z?N(cdJ@%##r@(|YXJi;a%?82>yI0>EVwkE-(vPP)BiNd%7M?S~i5WsB zAeqJi6I@hU3ummJ;3d=P0%)djmH;qu(!ZE&3B6va%60q<$l(2}g$Feyv>5uiH+Y^{ z1YA0^o5C=GLcEG>>a;<#DypS!GMb{!yA$%2`f_crgUx!FlC52=;!z4#7T&pGF8ah z`=>v~0H*7~r=;A4h#J1+xDudLSm@QQx6Fsd*8&2#y45(nu(|q z#C{1Nf1>HqGs4+72{mB1=wUVNsmw=m;@9Xj3Q*ao8_Haerq{$ z7x3)kaGlX#q*h6m(zcep{LG#cBdr0M@tZWWRS}v_t!hz+{t&NT!jR5l39$)g~l!G{4Bh zI|=X}#Y9YRiuWNLR2s6P03`7Q&m(A2>3r;CAmnJp7SIF1;pW)GGK{;7D^}M5bO+xA6m5wZrEZPxD`&a?6Gf{xm4NtSsz*G;+ z{EKg-1x}|3;8P;8?@Qoa^=cMjJcymgO;y6x@wp`e-;p!|mEWlaQV5tpKuN&mWs9ZxHQ{5>YRfA)kT}j20 zp>l_4aP(^cj%ArHj{Q~L@ir@yRMicl7Lnrtm%w?#DDwl^yIzt^o1MTtkj=%b1($H8 zSILk7w>|bR8Z9nbcg&Cm^g0p4>^ohcxZ|3co&jOI3~rqn!>E=a@-=s2lc;&_*o<6j z#?eOBjg1})Kia3QdSF1cd(eAGLOiC$_V=YzZod-C&2-_pc07>+Aj=rWY{JtES?g0d zw1AuqWdCGa1t8Z9bIL4pb%2Y3_&B}S%zNs3eh93_LFXY6g9IMbPvne-;2~ptUw_seW||Rd1}Ywm0gO?OeoiaxLYe%Q6Y=G)TV63}>G!Ew?2V&lwX;@vbN6K&JEO-QGQ)hc$yFKUQ_Yvq;~eluj(& zph7oZLyHsGXNWCfkWBS}iZ+t9rD0A0u9r4DLhgXi5E)d?=xlt!RkqyYIs}A3aYF!L zorlPjA$0wrI}zi=oy`#dH{jPKo2FQ4@fYAu%`yP8$x+B&IUuh=HWc)+;)FqtYygt! z>-T}7L^m2DE+e2YyQ*5LAe&xQOAHjlA6D)D5Y;hrdjL0oUR~jq*zlAwKx8 zfE*h97KeXClM_dJjl=j$30)Hak&V^q>2~3Yj)%^k`tAc<25)+ODqAzlTe5B)kjs&1 zdv9v7njmBdtDHTjz8JB}BIszKXJs;CyEVhUfnbGgK8uI#ct?&*j;%rgF#Dz7ro|EC zXynw`gBcDM)(TffpA|8}Acv+U>97nzrKQUMxmJVaD);BpTVR70@fr?k^E&-(*;{`Z z?$d#uoa}jEI}*E>jsTwmi0hMxy-RpE0Bjl+(d3zA7*(Zc6p#Y9t9Wh|+oe(6ZzpA@ z6mi_vpZZ4!qnpljShoq?(Z4ohXylF9Y8Zu9AgF0R+1M06&0XZ{>Ys4@v>@2*Q!5Gys*#a-U8T<6M~?hh;D2^4>N{YKwb)Pa(nRC z3_~adS1gJ70M(S7g@$Bh32Gskzj{XM7Oo-5Lja1bc5ea9$Gwqz^ZWea=%Bc6k1Pve zwhT@p)|Z7d0YjALW8s%;M!Q<`=ZZm&!liN49ZN%}atjH-uK+U*EV8lQsLmr=Y_O>r z9qJvN_J^dT;xakau+u@i7HmbS0f61)N6vl(ynR9m(4*QV;EYnz8 zLe1afu_hfJxoa%iZ?*3%z6+DH!tQZZ3UG|h|0M|e2n#lWwBjLN!UCOoUG{|F56y{5HN#7`kFI9{P*-AAO@c{Yn7`;^=q4@8_9Hx z9;t%1y>$=~=m7zC0IOg$sfitZO6nsO==zHaVk_KeLzID_J4G%faZ zjOY_!DpsL8Z02>N&GS#O5|Wkp{@9%)J!iAlfbl>b@BWY_{3=s;*l`4D4Di=+OI@*S(fnopXE-9(`GsdFI%j)2Wm05BhShT|v!NZ`0L#ja@Z(+2Qc0k0)c+J~^D z5G9ST*pIeeK#Yxo$5xLz(Wn(y2av%odjRAQqt!OOh9K*kvC>UYbaD#N-X^ z0x@ung1uFb)kz`%ZZS!}gz%%9E)L2*HQkFYL5H;#?(c*^0G9x>beDuKJbmzEU}#b# zAi6FPJ9{9AT#aifm&K}f1l|dFWA;R7O*k^rHgDH(_ zN8Wb7e-wPVoLO&USdHhfCn+#U)@${gI>5!7 z^b(I3G#0-bak_^cTs~dH6))s99~lBbbWI;}%GU26Zps>sXHgHz<-_99;R zrvYjC1>G2IgB;4JdHCe|XhgQ=9W@15K*AuRHbZ==(hZHeqHv0)C1Yq@CFJ6okdOp` zV}qe0grEv{o%4dP!7h|eYz94>h72Or-2IfD{_YhRfP#X!7`{%T=Yn=QFj^Fou#k~8 zhpN!aug|m^ii#_?;msHCiKhJS-4Le`w2jehp9Y_Hok798+oecXzu?py0ocAwl!nneUo>pC;eb5P+=qu0@Xv_G%yf zGEe|IAWUeG7NfS%A2N{_efhvwS&|83GZ3KLlgXorc{(|G`YL^5qyVQxqyV<#^S7zn zONJ&E-4Gz1Re`=4Fa(inpr8QLf5AIoUk)ap#9|?(O#!;+%a)8c^}s|j|3pD zR6(yPwtBS_N`sgV?&$-%i7HKy4f`$PmjR(y+;L@S;T=He4EhHqh^Q!@hJakPfj7E> zr%==8Kt6S1AER)PL>&UiyeDI-hboYF=|a>+1fipF3jpE_VZ;p`0&Hi+)N2gF;pnjd z+gLIQDe;j+>s^W)14UrCoKORLdtT zdzuKgx&;sm4e(wK0iC>7J8ZbbW6m&}262yMkx~+&x&$B{i}WXT@InW^;V zO7}gUGXOBA866&UH?1(eV>j28SPHw(uwUH*bxwG{DKJD*9Qpby<}98pxoo`N9((leSAt&@p@V6=dGzkd_g z843pDf$eU~E=2u&9w7}`X+ZN3muJ7`#?)z;a-SW?gh@I`un;vO9pgqM+Z+QDI3?E! zod{YR0t5nfDCI}M!M_dKn8l}YNJO03E45%aN9j8`%Kx+ z`D0#%-v)$U%mVblq%eKaT%eHHN7j)vq2nlG^uiRq=Wm9X`i6iOw?)TJ1h?tXvV3az%vU zer*29fB;xvrbkaE^dX_a?Lac+9zh(k!5KmWwo?F+kntP{1TJyoKSD@H_Q_`4Z(KsW z2``ji6T^3jhTR>*E-?T%K?1|2UBVz5E};P83=YI$e-|W95Zb!2$?C?jq>n;~2dZZa zd}oPjRtzR8b9L;Rmdck`zBB<|`67v_H_sdZ0^LmfDa>*raS6ejg92oHMgszfaVcEy zt`@`qIs#pZ94boeEeePwC1MN0bv+<}4L;ag$Ri!i*6@J@*!4^fz-B^|fCxy4oudZ5 zqX7Znl?i+I14v_-r$7uDuzTK;+bY*y{SFXu2CohZKvp+B@kp6`ya_ibh{B$BgA|Qp zsaVijxT7!`5TH8WGhzq@Te$|SKoRYq zvQWTmrZp8IF!y!T_|>pqfKt+8xS(tfHymWKPlT~cD;&FPHL+vG3Q#4s92lMuvbz7-2#c>P1$KKOA} z`&se*Xfzb-OcS872VD&u$&^76fd*s0FNQ6n0)6tP!bLNifn=Hho+jC<>}F0=7yPAQ z>#2=0NYGcG)uo9yaJJ7WH6E^1-0mL{`yKyVIj!J@8YCoc38XFdOb|BO@MZKW0x&0( zqigQ#o26WdRh5swmM{mLc};P*gVWPVw*v!aSyVN{ZD(X z@wmV`C*;Njh~(=U0!7KuN&-aa+E05C@N3KMH&PWCyFfM=uPjd?F4W?m} z=9|4cBC1x34pEduk5>_ZjEBn9UM=?NYNHJ@);q*Xi8VxyZC3zbCkfySDx&VAKmgJD z>ie)4g!~cb&A2YwTSW;23i8kDv9g&Hq5oVrmemT_0KLBtYzVPTgQ;M(N~)XOM*(M4 z#PxysamarR#UUGX|7ljy0lWGA+GpQ!1~#HbG_X{;4Zw9w5LcZinJ&QQ zZ-FAfI5uCXb}7a6TGmR>Sz%xe60XDaA_U5>PZl7Qvy>mH{kR4|cbz*}T!mC9{zWQ? z!nj-_Dq1yQ(?$WFelbzw#Ty1o9bI*djrLI49SzYj0C4~a!0O%#AwhzR53H3v?|(s8 zS-l}7fWWP4o-V*bzvmvsp=aXGGlyu~g9GOEdxfwXR02to z+(`+EV>0`92s_d_ITeXzcN;bkpFd>DOd}E?f`=Xh*j@q7qRJ;g9)6jWPPRkd03J$a zS=ZWV<}-lk5#WKY9jF1oJrPopX_j2eYWRD)m4OK%Il9YzMj`}G0fW^blQjamNgL&E zo~e1pDAzG}(}4@l6)C3x2zN9byWa6PflG*&8kzwZP#|+>X?Cgrzprhij;T{%=*Ip$ zT>lJ20ABJC{sOl77#4tqrmoJ(NH1P2Q(-UngW3BAcXXsgg$~1J8+IBLoX)?mw@W7aHBwmKwNij zvl!kn;{Hpz7q4F=JH2YX?+qmuzy5_sWm*3m7~h}j5@(_t$Xx;?gqT za(=#iQDEa07ah%7032j^34x*j1+WbkaY`SzQm0E8ZZ6h;A2K6sppLF1qu0Ukhlp94>`&vZdidL0XQgDj^NqKx`Rf zpbJFK0}UBB?nEgE-k~4@NSD))!)KADNt}$ey6b9eT4N~wX)x-HMcXz7t{sR{Ix+UJ85Xy0pN&heF@PRT zQXSDrQSId@1E+$_d6mT6awjAXQRk+~)9Xd)Q_q)5ZFNWuJ^uLDSI?CCmAW=~qtPEJ zG8lS5dwP~R0{o#S>9^T-_bC7iB_+VO!O64}8iKCoje*1h937PcY$4XCUniL0H4l_q ze6MCI(ejb=5V;&6Uecc5EVOfnWAzsPhTD5ZDI zU2juTe7XPPLE|yg&!-KeEovxaX=ik23gxDXRkD-i;7^^IYy^+h-HzbTDI@?Ji0*R! zqZbW8u8dXR`vW@=0t6f@mPB0j86&|MQr71$Uog;fVQu=->4_3Ohjb*IU3@1*Ov0~5 zruS+hnZ`oT*g%&*@(7pf@#`!#4jI=qI}r8e6@DH7&TvS)m>ThL#cJnuSw7PBhVgKA zBgw#Ab|(D(Pr!aS9B6IbnW_F3G8*@FU-xf3{8zvygK{K(N=GdDeoY_2KyVYo3G1l@ z;Iz7>yr;VF%PcgTpxkZ2*$H6iBkXe5aV5yYAB~Dr1;7=j7}}&?#uA&+Q#G5FAqhk* z4i5KUmF01f21HCh2KJY#^s{k&0HB$Mp(I3tr$1}7TrPkdac|f3zr?F7mK|uh8;UxC zyN_VB8#(2`Yl`J_d&Zmep%@}Kh;Q;z0G=5no~DOqz-fEKcz{)0(}!k=KPRu{o?qG^ zwyNKAR4a*wLO21!-M9g^@g$`o*dzH6Es8UmoYY@UGlkn`qg-Nr-oY_i*3|0iG}nVW zp#R0ve5zIAU$|@v5JHFqd|9n6%|2_KO%6?Fp#8>6FBs%`-$Bd)kbw#c38diZFaGm% z9x;LiFighQub{fAlqvzCQ}hK$m;pXo!*0wV*=+zoG5J*BYaoRHY~2!vF)Rw8I=kMG zQ6rCNu^>+Y?jf0qtxnU>>j11J1>6Gj#}DB{NFW7N!i~=uIs_Er!;|j_e%hL3?O9lh zSOiCb+57iDCm}e44ET@J)Y?)byiYGP16a7FE1dSlU+M!AWObL-PC~?-A&!6o@TT7r zt@ueGA?Og}+v;Z%a2ai1jUKqISRD<79h1UGOd_bNC7;_)<7T-oK34;Ov*@$@+1EW9rf7Qp0@F*C3Vj~-?SAcbGz7i8t4 zCYQjuw&OQQlbT~a%Pt|9X*hqp=5xsO0- zXO9Xkn3{icnKXEC5&9e)Em(N=L4-w={)YKzu{Vpw`~&b665Y0(*(H zfCL{925fk}(7?H-PC($+Oyva|QrrWGWc-C5Lszb|@M3`YK;I1;;_Uz<4%HeP#0YL7|JOl$gu-0spkG`0o1iDpJ zDHJ1b*qu<74K!XBJ0dpehZ z=1PP0v0sQMK5FxbmAGh%V!@mLe*wvJ3qY=zgu%fuf;-R12m$sGK*)d4PbIbh5I%T} zvU)nkohABZ=jn|LANH2+_$dInj#-g=)2B!dCT30$c*xG4+8!%QzhYI6+DG~*ppb6; zfdPQ`^|pE8+O|tGHAi_(Nt6O+FZwhnUX}<0h(Z|FuzIXbvz}$O6{6!ffCc8yg5(pY zt|i%5*Pw>A=@N$>CUZ^=4}5?;k=4c+)Wc;E)!PooI0#9}sAL*TQEFrUD6s!CfFuaP zi*K#MB4Ta^H~Z$g(G^e33Th~jkYP1{vQ!mWQ>t6m;An8kF>6)bM~vd?txN<&9tZ=R zNYH>yfWyO}W6GCOBW<>YqMM{IS9iZw<^TVdc0RwcBzFP-baltwB;IjL2(1r;-O2s| z7$lU*#(A$2MFep{+yj^;7jBb?gI9WaTYhW67j{Rva3cmG!2yXC;t&q()_Yhmx0o9T zLfXzmyc20ptfcJwOGJ?ovy-*1bLd!3CG(f6q^1$DjxFYsU@G z>IPE=0FXRm(6*fTIe`DMHI-gwr=3qusipM(9|dq*6|$EGv?YNuEx!(mEGEI%TnWI_ z%QbbVS<9K{sUoRPsg7yQjlxR-vRM*2K2?v&Wp>ZWX;GnHt73sm<4po}Z3>}qO}5S-xO5CN3Z$m(F8 z!kzxBl$NAR?e(8@;Ti;=?BbQ~_rOn|{1=RV@Qglf$;Sz>&*KiB+g*b9EkK|Ob6Rhq zrUCrn04B7j_yu_nl#%Rk^9wgIqZctL=KyH8rqowl(t!m)pcKG?t)|0wfORrBH5T_X z$_!ux{XiCK(q5@h-UII=0X#3FM+-7ol$Bnxhs9kyek-b!>~<&+R4or*$wOW8iqu<4 zp!{R*q@*JUpI)Q&Rk}G)O$rHks{;dp5nGVh9zid#B%@i6dc-6cSADuC%=nthpis0# zmJvw2)Oq^@B3Gz++~K`IvRw$rCsRN;v}o%m@Jv=*$H3 zi@DoL^%d4K-nXhoL<$h$E0w@Z(S@_5P-GGSeo(VjTU2D`wa-*E){D}7L`Yvk-xp-{}09}pUVQ@$uE6dfrE zSTgyeT=NQnYVgjUaSAB7?+FQfNdvO?vQ%^?X9+929F*W|Hes}{NB|y#^wYn+ATc|% z6*&)ct7_TP04!KA+blUUyKfRMP{afEZDiglTO0FzrEwv5^7yyZkgx}MnuS<}q9Y{t zMG*i9+A@=WVom^=sRZ!3rzz|G5)^>A7YZof3xOQ6pZ*q|G4mC^2M}=G7_~pZ5P*>w z0sJL;a<>Z!UFk6Z26kpDLIX*w+71xF@YGM;GS&yW5%3C~05KmlcRt<$l(J9)AWZQf zn5poG-;M!tTGR7V@Ridh?y0h*0l81(Ab>~kVN(8?=8T&pgA_8_GT8MmfqhV#_?PAW>hX`*%<}|5;5qqp zA2@(1Z3(n7Fn`Si;utcxz@vd%F9kvNFDeGEcuj7R04fcSQvguS>kx#=!_5L7r;G+j zI*`r_WnNGp69OclNhJ-uH~?YUHGo2CQaGe7lQBM10L?Iyo&s)QFoq)pHKqmk6fzktZqJa-!k)rH5e>G}KDNWsERN*Uxw^AtIzJ zr2+*{c_v`TS1^XRX=K8&Fd^p1^0iCaGvVZaHGt>qm6v|d)~_;YIsowU&db0b#&Dei zz&$g`iFGgjMiyvs2LR=lWDx^9KtVTt4X%Ovl!Sdq7Ys3Xfo#SXCd#G{M8Je@l)L{J z^Oz5^d;yD`7yzy`O_T`&Ab|y2v*1u6Z{g@+&K$BbfvjW3*L>^ofGsFWN(BMAAdc7t zT79XTM3_jM32-OrN+~lYQ~xOd!96D+{BHr0Jw*c(!Ry1+(usYR0Fo8lu4nc z7emVPg{LM={c{Od9bfK5ye<(?{>|J>evYBP=?seE_aK4LTvu5rx)YwJ!SYx4D|K}K zdmAJ$B8F0p;j?EwwnmqdBLM#?RZfG3DVUnDacgdg3gtsNlK^Nd*%1_{>j!Y_o_6$z zZRnRF1mCr0f9`fN1)C*6`0kKWY+J)_n!z&)71y=Aiwy(tQ;1MddV49`kxT%EMWKAf z2>{3|JgNw7yH)rKj^Kf9@YN*{YikwtP4-zyq^5!}mh;2+&Z58+BX(vFCJL7m!Y6BA zCi>d008e11!P9KZkp^bx*a&!(nipKj=0$i42uKr-w{PZSqA@6<#4>XGR1lKbYQvr> zxG`5$btC83m8(Os_k*fkS_1mOo`&a&m(K069eI)|_g*jXrYjRu9>aMhLjVGNAWncY znNmo0jsQHm^0R$_Aw*c*`?8fDfH^EU2KFNYwxJ-bo;|f_XO0W-fg{O^Yr5g}s=rg# z9oOSJiUMwcNn*JKfw={<13S#CkImd}{|JC#{S?R^OZ=RZ?vZlDOLAZ??W;f`Z|e~~ z=Shj)GFNB($-huoBsGP2@$UM1oBRskl5Lq$C1WGPDBme$Kp)2FJxxLvzWB|#rvU=X zxtYKl)t5jL3t{Djze582h?kP*M+w~sKmcI+kcXB&i7|Y2-4u8SOF=TEJMvQ!;K4nK z?rGDU2z$SI0PJb+1GZp*uJiL#HX@7{`ZNaMOGBXdJfR!oghCBq*Se9{S1Gy9amm-3 z<0Qk=Tmc-hm(htRW=UdOl4p3qM$;y+xI-iW<6SG0M}#)=3Ix zlFP%yw!*{T1!RYY*+E-NUTsAKfL^*%eUE_CC*Y@UPY`zGAvWYkLfSKi6pJ*mVxrj1 zd2qDpe#1V%fm@s0Ya_Yu1AUk#u5Oyw*?@=@!dLWJF*H#Qai^e&U#*i0;|nvFwZau{ zN?qBKn$em-;*wb14`sYz8wl7j({KornrzyXCidMPsSxr?9mHkauUYS+P?e_Btx`1e z^Awu^U~FQ&9+Sw|7?wYXTA$@M2L`mKSh!1wzLV^5W5Yq3&mag^1NaWFkW7H!qL1fm zIxz|ILOPo!0Vc-AbEFnfJp&p6GsR%328$RXO}iN9#tIz!3sSBII!2CM{Be(2vZnN0DN|=Fr|b5GlKct zy2dNF9##T75fTm+%~W?y6grD=S}3968pMMDVDw;B4hp6~Z2o}-H{XCW;Djy|3J(D7 zbcA?TaZKr1nyE;vDM(j~cXSgBTVD-m2BfZ$N>XhBEt?z?`gqF^aQWH++V9v+ZfMe@H3LY1ate4qvO?+`S~HW>kti&#$f8XW zh*`2{`>~<+=CmYAsiWV%8^u>3dNJUCgIAm;v|*-!7?(o2&mi9cTn9kdE>Cz>9ufeB z+J&4BMAVVu>6*5&or(lJV+Y~VZD^$oy1g|sU$S2@>Yl2bf)JGLlHJ(ab(FSq$$9|V z{Jct^!(vk%gTU8D+FwwdG6lF(r%TJBX>gPqJ;({{uf60pN$Kqc{#AU`5ci;YDId@bwh{p&|&ZDYl;m!frb6GeQCMR#rRbFl{~ttoSxhaOo4g zrCdP|;NDg_o~{aq5IpS$B=J)k>A4xoexXRB*fxuMiU6;u-36p?s%iz%KXf_%?VDwQ z!vJDy6`jBdU#Z)+Lc7Zq;RXT`H)pg#*qdAsOzb5;2jY6Q6&zvXzpE&v9grOU!6!7M z3MwrA+^iAEBMdvndk_H0ZB3_lb_`_g+@d=sO<}}5Fb(Jn%QY0Z@PZ|G&v-@oHVt^o zkpID{Mw?)>@X@A=)u;mz(|~$0rUkdIPP*FIf2R~nuMlDDZYuZYWSs5M$j+zhN|x-kFXlX>|^uKn;jBK1qpaBmf2f2lUJk+eT;OKkx(Bkz*pDS6D^gIvWEF`9W?ud^N#|42|Q}pH6NyR33Cww zz`rW$C_kk*5Y0hR^c$?!=5$ai-X znOi+1NSFaYgsRm8J)^$*5|q&)_2(*ctik0Apbigr7!~+!oUrVUfMar0j($j zcB@lRd^M+h|KITgfC!kq`y_$&wM9k3?6+(7LBLwaG1}RgvpC5yE2LM;4Vl9gq zca558Qk$blp@(`2J}VZHU1%UahB2^k4zp!!%_pCi4B5=}rjE?}8HKWsHXJZr`3vHT zSA5KRnyO<3a?|2iaHmGnxJiM8gGycTmF;3OaGG};1yI(;DS%qUQ;0Ki4F0(lABo}G zAYYnk*qWuAkU-)d(doe=a(98RHi$iABa3y%osT9AdY`itRUgBSI{@T*<#v{^iN&1e z9=#Ci(j{V48;p;;OWNS8sdQ1szrTrzEFf}C39(pc#Og#P=IKD>yQc-FntHQnWTlI90J>Fh5-4C$Qi(t zJ$E_W_W+QE;+{I*@v4f@JaYPZRVbLR*SvXy;T z$i62GW`1|n`}6(%apy6A-21xcblIG%7t^3k3m*PB9<>%Q?kuF%*-}uY>-mdW0=2nGEcYoeW4(1i z( z-%{bXXk`EMHPw0gQOXMglF0=uFuMo9&TA^KGox5l;?Fd6x-)W$x+F=ZL@n(atBq3Z z8QI1CEY5fKUays;bL!1@nS0NU2nCzUeet&{cmQBl03bjB=|ceJw3?y48$=1b{W!|F z)yui?+K4VY@Rjnhh+l%F_uIK&M8tFIQkekOX&eCc7`7dcLqHo+(At$Q&VQfCX0J<^ zJ$mY`{>4NE$-)bn9jN8*8bzY!y!xi#VmNBk^3Atj3`xEevIrOh0C_nE5RA2f z$m!aMZz)bf^arRnxt;*y{r=)-ik9rgj&4w80t~+6FYYy&%Q59XseI$1-J6)YD_EE~ z!0z(by#O161%Aig^jIi<)!xr(;&VavzVbWC-#*XoD^5GLcL@EAb{MMHqJxQoN?7pb zEG;C6p9wfX?5EG%qsG68yEJ$qx9IEZXjkYpl^;EU65ey-USuG+j6xy4)rKUP((}fB zZ06j%3hUMxysr43Q@%v;4SvivceP%bodW27)3D zI=v%jqnekgoWj?YE~ce12@4hdpg&TGl||!Bwu>;Z*zR)Wt!;$7I49Mo1>b7!HBb+WXqPFoIbc{?YaMto>KiW@@WUfP{}+6C z^uuNtED^rs=Gs!EqE_PDx1CPq@&E_UNOtCy?23vwTW}H(M`8h4)m`(<`$Pli>DO6So}`b_>p>a)p3UDNw0 zElhU%Ndu=cARB zGr;(#kI2+kbH`47JYhMyfi=!ppcGvQ!3Q4Eq9pN`i$G=Hb)nw%y=3X^d`j}~FQ?qM z+U!2_m@6E}4E4xNe1|3&XGTyGFBVAurbK4hLJ)k4Z_}F-3m?VQ=jF{A8Jmhasm}I% z%B>ME!|hN`X#h%h7!iS*T&V60BOzL}WkRvmr645i?K0n3a*9u1fQ0Q$%Y27i5T|ux zk~r3JCY}xTw*UatNGClEj*CIWhzi|0zv?^gA+0K1grK{cXxERc+S%^=Sui~DT97@}P3GTqZfwQ^-Y2s81SPpz8l z5C$H}L_$F<&(}=vdXK$}Xd*|N%=fb}wF;(QQ z%No7%!wHdnp%l@&neM1ZV!dOBLw=DW>*f%^J$o8yX^%pUFvb)%FcALn%1bxxpb43k z#N)#zhm@)si&rCmWRgc0xa_LB8W}o*t6vBbc>gG^wHlC~xKFpvbSn}a6mTanV3}0? zf4h{xkwr8x;rTE6bm--lkAzW}t_1K;uY0<-91N-IisHN%wHp_Z_(OEmLFC{+hvEU8 zcoc%8CO_2O_?kB0e!2W@-fl;id2yG|pW}jz*6PJw9CZB1L0u(l!G$N;P+rz_G>5_t z7y?od;YLooL)NFG2b`8Ntua&HF)yQ~pC8@Jb3AxWzF8I~Px0HA1tJ0O(fqef0A+iZ zv5Zx#ypC_Xx?@r2WLx6Fz&$IrweD1xGw1=vUMYy7u+SsA|AIk!AP9W;xLP+` z4ace6lSI1T{oBuF!M-12=?5GODG$M7Hse1;lIr?hRWYEfNiaK}DqKE0Bk(L#e=4!= zE_bKMVD81|Gt!wkV(Zr`M!E&9p2P$S7w&q0nh%4z;zZ#svBrV=XQhw_AW+sQI-Y%W z*(lIJokvYOyLUL4N(OYua;w|$8b4@yb?Kwb_NNE!Y2o@v?e_zL`cZlI>pUm)KYV zgx^5Yc0`55rQ-i$s}r?5GwUFgy3s9eZn8YH%L?7y@QIfo?)7Yy>U^FxWB32z<<@W> z3I&t3_8!-t&nHGf>fD9eN>FBo;x@<`y#^h)g1ra`Q08_l040W| z1mr*M8UupVH-fh6-wD2+b%8U-8g$^$xZ6l%Flg2 zd`8mArd^zBMSuLP@3VsX>N{2MQ0x%+@ZQAqFmw(os+$wPSKVNZM(Jno&ha$y)x2=5 z_m_7o7x98$W@tgR#i<74uV=Q&F=`#bRQb|{Rm(c@m;zLXRl|#G2h{w%oee|%;;^ry zP6{1iFk^UHdj;})g47Zixkx`!e?BVDK#{(gxw}2C2t8of%zcxKJ%Odk(Wy*xX%?Gx$dE z0I(|rq&Tzbkb7Vv3SG~q12bp$kZ$hty!O+gv3GpolI_c5U2w{AUh#QQ)Wx>)%M9lz zc$MqjYpTw9(02T9s6YSh+yyTE zCOvU0&Vw+wym=XMFKB%S|Dg%49ohDTST-D&!|yJ~f4AC>5@2fE&@MN9zxQqNAosQQ z8g#vt4ckmWz~g(YaP8kGkc{jYyQcpvt9|;)2Gx0&#XUQ*1C>ixddE(~OG_Q0valBQ ztB;4twqIQRZmNH(darNnHEAG(W(70+c(7ks6$4E+lRG+VlrFw<@x0hlRMq@MBKN+@ zay^0AH^by;o4mKvO1wPiBunv-zJ;H{{9|PhaOv^%fw0~VyH8z=_R^}k`iFRlnTCFrh;r}Gc z$4EGzhn-!F_8xJI_9Cs^osZtN;S_WUCAY=|<~=yjSVE`1^MxpujXuJ@R9q{1e9*#j zp-FpMJ~U@ck{p@#$)g~nFivwA zQ)ZUWw~Vtlf*Mt-S~QgcJVK&;-P9bi;$xT|fXN$dFpcit(SV{c=NT$9Q$dgxeG?^q zEQ`-o#dDw8z}=Fii2#wIj+G+A5u?LzjO|j=YJ^wAj32P#*SMok(9`tMz#o93vCPMt z9BQ}D-cBM{3~c)9MzwO(2l_X+=@r3C-$mc_E)Rq(rG;_hSqjdM$|p-|(qj-_)a=y8 zB9a*kS}{++ti>Tc<2#N~DeG@ z?wd4$c~%52;LMc6HFTfSDvwzJmKF9fVg^xr_b!RYw#{9Y4C79%5!6KIyLF&!$1O~f zR!lC@b4lkgX-GEJ9GaNKnRo7ac_Zd3s)bLY38($9<08#0WroVV@~Vv3%DBGg@|ov$ z%@T32n7CG?d}?*>Nx2*9GoQ$cQ3G$ZMw{4oIC@8rErMgvdpE96J$gYKGXafoNzq;l zOQo!Kg1#$@?!>vHhYKl#WJFWWqJ>Vfn*lN zJ2h@`)cKOu*K0zs?+J3Z;sby`gT#18j6RB#St++UKowu1ZtK958ytteEq+^UO_~j~ zw_kgn&w(N|?ApnE0%&`23re;de|e>-C9aa)`_`WlUAGU#+}6~LVN?3q?n1YXrspBF z)-?K`p5g0+u(03R#YXGlCj0J!Ov7JR!&A9-bAc``sXd215S0C^@Lofb4!Dt3Vp*M> z!V0DA7707`qPIzkE&W5>9p7312f!)w%g0Ysq`e3%kiLTeUjl$LsBySNV3+^t@oTn$ zrJ!gCTX!Zov!Q_;*P7V((C9EGwTqm5l}j{>BI5#>Y)L2nC$d1%N~@(r6|=>XZdi)- zch)-57aN~Hi+Xz$sb)$rNQhW?%7Scj1j-mt2qAvjJ_vdRAD`@YfP$zji{ydhUdH}> zKA9)Zk%K7t?3ophj$mNkbxPx52GC+!91h_2`+#s1hXHS(b$UU)-u1}`Yjm!c**u4! zA$=?PUtcpt7U{~qEm>CQjwhIgZ5qv2qU%3;9%o;nd~y`P07(W2?ihW@wi^So{UvGH zD3~|@&86$2NRK`JsY0!Ncx6tBnPjUW86BlRI&|3vZ`Z>a=$Q|NX`TmVd@vAmM46%C ztZhyLk_+~T_~J5&*djnrG809WEw@ji`L5r|FdU-|Y>@G(B6`fCUL^euwa1(^()?c-UiD#zQ_@ zTXHd*`S4;^%2$nDF>f~KBuy%F)C|??2TF4SlE{q)1zR#s9>Y)2?!&C4S5^dskr111 zq@P0}>fC`5ERxTCe7V2p<%FhTl2}Bt-1UNFmG&7KZw8Ht-^m-*CF2?GY9vq+E1<1(-9M%gQ_&C6oJWIsTS`}; zO`aVSu>I0>bo%F$6&d^NPM>(PhkpQ7p2gpD=o{=`u}m%5#DU}=fjoaf`UsrFU7fu zHb2<(-@mfNTs&!s2VaI63UjCBUXLxNGw&>Cw@{MIeM@o0$oUf zQ1EP@oNzL_@WNG`nd6kwxG=*)7-(NTK>cCbmm3&Dv{;vM$F;wjv=LtY=HV$scy|EX zV`0QO2G;j_N$zktQaGaSx0h}&dB0OT(nWH*A?~NTzMXBE+u6Q3OL;NGjo;-t)XP&+ zJt(?1c;p~F&a_i%@BrpuIuHIZ-;q~0`YNUq5|_h8ne)&N&+B?DFL`#W#U%(QEezlMR{MUBEvw9?da^QHK*^nS3SU;IN{IR zC~!`62XqIKfE3yAK&2^0=@!>_JuTA}-;#>+TuPKnmY0-#8 zfU#DRoaI?_SByJ@B>%y|V9vz4*CPH$d%pFWO zPh$i1Xf1%WMFQBu``Hq7$5Bovf*VSn!|pv#oPh>~GF(!_(Zw_#vYHpTZAq%(*miNQ zNDp`a_BTX#$RvKc(hq!H9l>kj?{NCNObd1tBeDgwaS?wk|;v?ZPBcb!T*v zD*DLlkxRom*Z1M&DaqbPW{ftBV6Q_re^AECErYR;UZ)gG5<>T2r_N#U_uBYhg-k8n z3bp;rUNa=0U8TB2@ism}eG%x4)8J=*@uPRj^iYAX|CDrvuUIG-FL74jA_wbQEP1(^S^3PdJ$PVZ`qQgnN4ab`R7E4M7rqwZ|#uW?@P;|9yI>hx?xMSlx!$-CcEil87QDOPBUnjoP4Zx1M@Q zqfPiUQcCWmAsqj#p^K|txO6OwY)CY%w-$o4AUCQ_xj%4D2cVSjoQQX|Ig@cTmAHWXTnGF zMG@^6e`5M8>Kd=H!T;oMqrr5BE;}MKg7$+Al_AvmokPv32=IReJI0@;T+Y@K@G;)cTdF99;*gD%$K5a6^}-4=sM!Mj&9CUW-d$3^6LUwN zLsG?o-}rFYX_%Fe->N~_nJc{Jx``B!(DZkW6^jD9N-EhspO($6&2BA!Zna)# z#0^h~5gjh@jvRds|HW*Fxda9*@|@midf+zsX6om`>0KP!R4!qS`zfy%78Mxj*Cw|g zvjS4pf5q|mODlsE*Y|@(PoA}paMmW};db{9{Ma0(oAexfp*>I4Dx3E|7It;dFedS- zrF9k~3gq!4FXO>6A)^Fy|I5|^2OXq_%;sbZ`i2B@Kg6Pw`ummU6%vb&LV?&(ZOH6Q zwd~F@QL4cOU`A{{>H;cL@A_AX`AyjCP85-{UDlovX2HvlOcq`gzz**)si!O}c;uPJ z6mFNFN6y;xwmOo>$d&L32f7p!SixnRLgf6W?aWSab>L!?EP5G{j4$r%ITah4X7TQV z>~S`FbVTbK>G($X&8!enhs53?rJ_#{n4sLb^T@Ob2@aw)@WACzvRa;h)`8xa%&`p_ z#f{O@AD+6GR;vbgL7k+_t!f?{$f?pP1Vm4O*B=xfgiM{ee2jw~1zY`GMQ;<6OoOw3 z?OW|F+z5ATO?lNYOKF)@;kzFDbFs61t+lp+*8}vF7_ydFj*~nZVHNbtuJB_HBCZU&Drkx#a63p-TPULP0&$q9? zV-JPo$MX2=_rBmdP_OZ$T;agG<{u9M@Y{C)u>tK=ib${I6-6~v531u(??mIMeXfeB zM*-bH9+O6QU!Nv8vK2%9F{6I9>jIsJ*H)n~q1D|{oZ zLgi7o8v)NhnlDy~{K;eS+<$`wg5?xo=bdu=0BO$Py}6*I%BZ`QAvVDF9j?@J-tz|c z<_i;x8^N`wc@tT0amPd1&){)mF9xdaijL5HcDoHMzB z0=g~cBU=4h!%fK-sl68G;fK(JzxfWAFSx4W!R3I{U`a$niK|?aI&8YD-Z?V$X#I~l z00u7pg8(9iHKa2-r^I98W2h;f8M9^-XWI%N2M9zgK z5B{}lWQn^y=n&u&t@>F!<<2`0*{IVgmycGVN-MfY(dj3232zP#{hz=^FiQG*mWc)3 zTU?OXJezE|p)w0#bXN^4Sd=>WpTtpM)HR>rG@>Rw_3OPXv?b@y+hz95bN&*}bgw5k za`xovz+!%-#Q3R$fYA0&rZhD_1{sc5v4ng!P0NHf;WZY^t1qhS9{+Z~Vl1HgG4@rG zNViXW<}c27M~fBO@=oAP2d~yBV!)@Pk9iQ1bC!j`YwCb502Witq;^dp)n3R3?D~l< z>LU}{arJT^8eby4GsfS+ZRihkZ~*lb3l2finky&C3IY=rKUo3%X$TphGm?(F7(y@) zyh_df77!PhY2Ar(X<2)hJJqvv>epd?`-Fs`Z=ugb9dL?#s27_8K?BWBMJhNz=(3IY zOV+fS>)-$b+rF?d>TNHje)!JhWK+2LIXt7Wk7`7V*>5mk9Gxq`Taf_bX@dNgh04B2%`)@+_i9DglFZgR z`gEIMaVfuA97yQQjFfNI4$D&lc;@<6%3s-llq-`th8x|Zs+IGi#8uluFSL@xl;^td z9B3r-+b4bgl9MNmzz+fWPBJ|jUy|Fd6@OGs^!YtY$`EzXsTK#@f@EQuhlhBr=PYE2)*&FtwR}$$qsN8M<;gdAcH!Y@)N; z!}22RUZ1Edo)zeAA~VY9&%0Y8BfJFAc=q_`?*a36pB1&*l_~!q_4}Uhx>3vHQm*gM zx{UJ>rh^P)$XOECk9nY@j_{hWY1C`&Hgksx|3E4P+O$*SB?hXGrMU&G$VbW1 zrTqyGM;9{P=EsssAOb*`1!6@3V$G(F!$`UGYF#{|dblT7_3-?H?swtOqe<04{fdg~ zr}Sz!jS|+3v1SFmnEy&_rNN5Hw#qj@%{}3ca+UiRkBZtt-jY&1Gl}uW4e-VskT6Pn zoffM3rBv;IyacnOl3jWoQiG~(9-O*6@2r|oXKVahyp0^~!A}j>7f)QQ`Ld=w^N84R z5%~n=zpoDJ?*sy;1LKesPjQ_|Xno`I^<8#)+mjbw%E--_pdIOrb#V;#hcHg1Xe_)) zhX6=dmYbE3$b!AhsA`-3T{zmW|1y1154x(QQoltczgxt#wP8=Q)g|Q#&g06bVf$fX=o&8zXSx+xZvF$04>sCQ-{q> z4ZU5{*(4?WLQmqdauyu2K8N+EBk`L*21ujC5v%_OUnXH+f*lw9TtgW|%=kR0q?*Hh zZ(Wp+8BKRHlqst7ET-Vm?=057rOn)a03Lj9J4cHR3L#j%K(3 literal 8747 zcmV+`BGlc9P)5sAh?A5Qf>7-+dMeO zKfYf`5b)v6)cl9okI!w+ZGH)H;J7^i0CBH*>NQVh24GdZzwwM;!k3}Fl-Hs4XG`Rp z3?YsJyZUR($}1|6{;wc(jRSOX06Z1A$ANw8i!b^2CbLk&IuDq71BSxWFuZ#Okm)iR zv=~w6_TrJy1Aue;y)TA7Ac#xS?DNh3ZlaA$Aqs|mwD_GMNZo^5m|faV8#ReloD*7F zVxRp{aliwRF9rbVKpgwcEa=bCDv_}SnE=4{$LILt^U6u3IOnA=(MpPEpN~jsDPmwWerq7>xb$a(6-I}W;hKb zYFYD37+wUsh6+;S(y(cQGHsPniuazhc?H>LzyS|H*#bbE>Y4yDg-2%M`7r_{)CK#R z3N}QC^lK0t%yb(C!7BphxzQ;yIM(A%oc_p_?Qmg=w{u#HS9to;J^&7Q0LX#>z!qC{ z13=pVI02Z3o`Y}+H$f4$<7mw(AV3IVcw}EI4_G8q%9@e+UIB591H@Co6TX7CM3T#G z)IzPAW{}ho%YlA?>y48Q^ZUvLIsnOYNJh{+02pvyJNW2-!MH66-V|x#JDhZ&wb0Kc z76B-YI0}ubqfnpYY277WG@BqXE0SHB*HG>{$w#YJZ1rjnbA}Y51!wecc zAerR3eV@0yW+$qhQ{*+}jrN!}JO87)Jw3Nk{y0HqD80!xvOP$v|2{L6={I$^_T zu+5s@nh{-41IIChClgWE3zhI8^DFeTS%k(;kQ1|FcAmS6b#0ISaII=LQH{lar8iNnC{mt2ITmR6h(WXr>T;|E5azQsL zXX!lZJG_`D`_gg&vHegwNiyoK-eHq8rMYGpp|WwE+dVkvpm5^4ah6|hJ+SeJmJo>< zRpRU{lguf2G%FY_IA*gTAq_vfexQs-hxw$l0049n4V0jC9AJ^4GfJ-bSq1@WpSaM( zcnB;39{^A!H@)Cqe4Mxfy;%W$RwY%s3;vtv=vIU$6e5eYp2l}pntOqusJUTf~am$=2d9%(mqTOcZ7PEI)MT;yt0 z0f4IxJQ6wuAaxBu<{E(Sd`AbY6$v67#Sp>8_z1H@97% z1s;InjsO6f=tx)&ilz;vZ)VpSMu2P)2jE)}d|5N5gsRk`#orY^(&;z5x}|{mY8=O@ ze8sXKm!BC4eI}L)0BFy*kWHttmYcW$Cr1c$kwgcHk1&JSy|?D^=IXJ7OaYuXQICW^ zQR+AVl0^UjTVU%ycmgF?XWJ4XBUhw46z^~6HM~@mW3tFANS~1kJOCg=LsRs?tPpcL z>}^x+^mN_&@V(W$KJSrwEbfn?k%CJ_s$AJ$7fX~{^O@6!)A+!97=`9DJVKLSHdoQ1)S}TuaP-SJO z%{N*$WY(irbsyOfO`p;|4){c=kh>o6vk*KFD~{nnBCNWRMkY9}Ku=9aDy|1B)=dR@ zFEx2}L-I_ci;OP>(S#fl-USEJ2S!2~6=13@|AtMd*4n?o9H1lw7&M5F_^X zG~JSg%8b$vR8q=u^QC4n$j}i-c4JZB3qmM@ZCpvgt#OD@U=-(6zriBOyB_TQOD}j( zd0t=#zynaxDVg^w%bz*_7={xCfNvLMlXxK{OjieMbaUk8SINx_=0r4d{dVJXPgC2@ zS9m0M0055wpzL2p=K)fZv4j>N<0!e1Hc22j{snk316WS zV{%T_OORs>S&YvqT#i%KR<2V-;!li(9sm%oOE4H-V)as&TBv0>o?NXWg5GF^2={aq z9=%6pxEKJj%}?-m3G=8;yMPTiI|P7L4y;EGRbhlh{0egIEA5gr$2=t4^;dHg-TsSf zB>d|na>diJ_~Ld2P!^>7YSxGuhr`WXzPZWYaj4LQ$%sWAgrE>y}%_X^e1cn_LrI%BF>XrX)=sUi(o z`anXTHC^!Yp9vX4U@7VKZVz$=Mg*B6;Q-LYm>|Y7EfM!t0-)mf8TGE$z($pLNQBEr zmkT@q$Ta}0v!)8TH{osoLQYrfTv8D0J#ZP?qP||3_{bNoWd{CrFC5^%g`6Q_e%~M$ zHa2`6FXpIH-WdQ5y=YGyxZ2`T&5zPr`rZ%y)9kJQtkj=Nl6=fG z?3Nl;@VQ6tJ=`U@tdrIAvE{Z&l*)uw2WRD*+9MendH>Y$D&WpqCUMhL2i-@}n9qC?Y!I!GeFC;*r(ldm}G%koe_ri*6f&EbPK{5==PhHdyrGKDnL zZU9&$el7gei(q;RM)9nR5?AHSTx$84S{77952t;$a z^oc+}kca!)o2W8AAKqH|Jp(mQAzkto*@V4NBy-e#G%PIu5XY`u%rz2L58z9d%?<$k zl@G6A4}l*YE*01k&MTK|d?{`jBN@wYSEXRi%y$eL)tr;18}(4QAtoOiy%ELBB4H7C z`eEct0sv)PsUtGXy2+xLV8Q7IfTXY^bx*fMfCJgp_#P0OkX_1Fe_f3R?TDcek>(GE z+sn9;zFJo@HbEC|?@j;WB=o!LE}@O-l2kxpflDW3_&3<_ez%GhO9GJJh%91o2vZn{ zg104?a5kBq-<~0aWb!~|{jmU$#enRDU-Ut{Xg29Mfe02(26QQj1$U_QiH!`>nNB2O z2UVxG|1`-LT!EDkN9BYJ!)6g;39mx&FcSA!N^E_%VJiUd#Q(L9atvjjLvQMYsL&!J zSvv zfhVaG9Ed-?sy2F-6;QVDt)LG60_Z9YI1^4&uLz}_9{`1!3(bQ}uK0uDmL*PY`(4&g z!&qdCT1=4lCnT-`Naq0{9zJc+by_Thue2*$Z!UV9h=t+T%t%4+!;dO-Qh7$;k4i z?z~^Y%%ruQY+m`^SOkGuSd2|5N4k8Rb?n3Acx3fdIN$+DCj(GSi>Js&Y@W2vL7{}Q zmG}3E3$gT!P`!=#iZF)u-^B!*~?>W6N+z)AH;Qx?Y1NK-a5+6j_MPnBAuOAEtJOHU{0I~%D zD0sr{6KT(|4T`WegW;N06O;mWjj10-VkGG)i{pm81vy@mt_J5&OGT3ekGl~W6R>B%XeREen~#8&Wq{5oz0lI~X- zbvuF){uu#4{#mKO0|4cOtj9yN2mq**%L#2V-EoqI*KuDYx6EB7>%;idz|nRyzk>49 zBVqB;Rv;f_J@0Pe&>u{C&WAZu=q84ic0p+n{3Jo52KBPFD0<*5!m~9s3y0m%AR? zzI#Z5mPA4lI^K$@LUVTqpo|`$9iviI#vLyR;ozKdn)m|e8nfyujxGPz5yc!sw-u;t zq2ca|iD@qdVbY67Sx&SAaR;hHy&yNpKF#d#rpu$%uxf1jN@m z4}bqb24?~avmM10#*TMtlM-Yd7tB1*8ZHr#SFy8N^Njh^b>Lh%O3p zm-hq!y^}*)004_;Y6VU1hSf)#Rq)>l__T-?4rzw~+R$?vzad2QUhr^XC~gzE2yvXX zJ9VA4J8`Wa_}Mi8f4H}I{Rtr?zIQ|v{SsI>psicB>+fASaL~Q$^MP2%hRf=#|EV}} z?Zgth){;dJpr&K4tN)`=S*@b4{uG%3I1x>^tG8DaYjdx2&FX(5BKJ{gZx6#ijlIA- zv5?tHNMz%Pj03Wi#EkZm*3le`yPk(bWX| zr$fTRIT9w00mzqJfppP`WUQ%!udbAGY_8nG(l8uJojdD!?eK<(G#t;9hBWJ2PKfju zOv*X;T|0DmIA!6FxDTND0kBgRs`NfGCF~b4QrfVyU(K)HG#p4tCmagN?M>1C56`p6`XPp2fSn1(d6~*vQsc$V(yvaJ5kz*Vv2c3SR`2i^6 z`=lemqYhcvw6A6J0+1yw&{Rh1oS-Q^YAWL+NrQcZ((^`*36tr z^1z3;Wo#zqe=_M_)Om7NBg^XL!_2DV!NniAnoqQR)^7bR&?Rx;4H0uWd0NZSA^-Cl zZjuET(+aRi41qjeVqqfHtpy?U!iRUu1!R<1kj-a3Cr_G(1eyl`Tb+2{Qf@~%f{+cV zB+dCAp+x-|A(R*_lT;m!dulzx-lt3`QC}E_V=*(|kXJw-5eGZ~aUabA?&jZ_(aN5w z$7h*700}!2f-|K8Jq0PaDS84o8CWc};XB6i>m#L588wHSbt{$O9tnN!`bhwE*GK4v zE^MLG1L={09@>$s$B?Gy;WyYnmg?|3XXT=^_?CZqD#$;Idq0{PkTrvriJc{|1%Vf= z7&KUu4Py*=i!c#tc*af}jt%l&GW#)z8ELnikfpPlwnmL6&6nD9Zwb(t7w-iXAy4aD&;=W&vpM4H$qR`UGzn1f(mf6s+stgW-WT zJU4II=%-2;l#0X4k*^@h2W>={5v!i?F13b{oeuGR90o`}F920k!b@ zD-z~y3y}!3;~=3xzQ)rTXEL16R8q2)OlL-nuI$5s(Euwe1h&Ma;rKpW{HNJ>!fGyn z@qMi2Xfyz1CU%(33xM7~&33$HV&R||P!&uYTFp8F!{w6lJJEAxopaBxKgl{}7>*|k zf?%K-P6o`mU1B@{$y{XM6%@GO26DjVbE@auJ}Bb(TO#X}GhXx;kX&`;DwUq@?EO&( zn>C-qsBKZh0k0sLfPLZP;eZDq8UbKxz>LU@3UQaO1zxL+vMD#b&TSIm0KLB0_GSA zQ9vA10h#EmN~ZyUgEVWKIGtQ}NN-GTxnP+mjoqU$ifrpY3O*)#VW1w98$4-l5RX4S zEm$<|@QOzn1hMV_{WQEFat%P}001e|-CrTa?};c9IHaAwTp!tyA0GxmDA0~VU0sfGpU2OI6)vd|JdRu*(4(@QV|P za3D5L{+nYeAl0G(bgOHBWs3sPO-erp>3smG1SG_;>Eb^G|2t6dA6IPcpZ+cgNEAwR z(e{#aYR3GpYH=^%XmR@rAZBAmzb=ad-5fA>&5WY^006i?OUb!G!f9oCHXFCml0g83 z@U<%bnMG1HVYm!B+7|MzY=x880lt7mwY-8~ypn3B=5yB<0|2^RC}kW3ZlU7*1IK=6PZF@ zj6qK;PlBfnzG>j)@>0%>1G~x@5<+AGG|vl)MFBuFg=gd5`|lC(Sn-tHi^JsuU29u2 z(hdL`Cvf10im>pRSllPW3AJrp!)^#JDX+|e40EZs`4#W7`=^8o@0$`zZ}dY`fd@d3 zA3+2J3aymThTlAfTGYwj>UK}9Nwe*K*2DsG3^!HmCN^e*2I>jfC&2*^z(jDeYQR?9 zT|j|KF7*UV8wOIn#8-cN7I7xCC0zySf04M}XT*VGAOMN;7070`M#BnqQOo{M9CNw*F%%g%^vIz zkGwdL3nocM;nQ)$l-vOTI@zx{8~jt^BWc*CZ=xa*%Yq3FwpD%1IzqgQuI2?>JXGqE zd{uT5Z#;4!_x0?_e+mu&XYv52;-{m6_+xX!1UBBKS|o1dg~@H|nDR~geb`%#=Ic_V zBl86Gzo$z@`)Z_0@08xg88J! z^x1co+;l^wT-s+`X1cojj8q#q6RWu)Y1dYd5F+wKHaFxCgaaM`55P+)Ic;%!AP5~t@OEUj zOm_hoPM|4CyiSDAj!J95BbiXrIPUFhf=9f9?778r4*+cS-}r}K>y8MXB6}76^$_RKpgM@cmQ@S;k<3_5?caQ)L!k!o?KO1JPrQGB!e&?_V2 z8C?S&2JoAzA-lU>^_yc2qO7aZrQEnFL2F= zBR)Z%VaHTJT{ELn!Bu>394I1-ejp4abufqx zuOW}k1t%6`H2Yq$622jGzVG-Zs%#;lG4AblGd-1L;yPt?`jJmW9ssJSgIV^D`j?~$ zTRa#`o`&_!_pt$#c+dl`zCtPBn-=SwN&r~Y!9}aKF6YB@?X1CCml@Cf3JS+K5SNYt zh^S-F>ToH^DDSDa{ug*E>DrZbzhbNzUszGwFyB(B$_S2T`fzq+oTfOh*;`j7yqZT} zDEOPrv=I@9u&~i#@-W`@9so6HTDlRR zVkl`_0opHUBm-v028a!n%C9{R_~dw)kBlbh#L(~(_0X{9Gkmc;cf4jn;=_TRAWM$m z6X9}-JUfd%91eH@CLd{{IRNM@+@*_^gXXdV7*0e%0_2X;FdPi^Aec0E6d0b}dbY9@ zgnN)M@R9$V|I{1~iMT|Lso>-|T`)@=qzhiYVNep^5Hk~YeMLs0%J5B-*xszcqC#L+ zod$xHO4i_TkhHaF7#0fHfR(B=G#|MYZw1sq4ya(2J0`>M19HP+b^sJw&qYo}I|@Ws zz@7{-l6>k=;iI@vi_A;yB*tuAlE!Cv#YzKKu$X_r*$yc3>n4LowuF12jeiB}(lrjO zKLiqn4gknI10E~D&?N#KlFoof3^a;+g#T}t;5CohQR_rF0#kTIYtVa6o6EO^k zRp#2AFa7kAQMNb$PF?{GwyZS;HwY57cksqI92melH_?yO_96gy4)Kq)dMi!!E7r;V znNmc00Bn&_Gyox6LVIMWWul~M*%JAL1rd(mKRj>+$k>%kbOUNepBe`|0O14x!Z`q> zkfx;{pjeCywg=6>up;2PGy8BJtj}G>z(W&$5g690cw!{<0N{B>V~4eDAVUPyh~f;% z=wi&mdN{pO0I0{T?TolN#n-a=q^V-lcG+vCuTyzyi+4Y^!=Q|oGe%iR(G2N@CpX-;Zz$ghf7w#>8gfBX)eYOkSNs^06tM_ ztc%@Cv?~%GTXF|MyC8(3j>?UiFuqfY2Wc+GhmU{*9sm!(ISt;DUWaeQH+4R|-I*Ar zh^Ymj8A_Du!FzE9SnpVhqR;TWkG}(2u;6myk?>*IanbGzL;8ep0YRi@Bn;I{m>MTd zmhFSF-s)af8?&N)_!qOOa+TjW5cs{+3Hdz|dI0cPH|BH+k4k$3FUX7!|6&~pNUk=p zp@3`4a8)ft>AOi6JRNhgC!qr741i^D017m8w=SayAh}t@+evXK_YU)^{8p^C{|6D| VBeH!{f^Yx;002ovPDHLkV1oUP1&06t diff --git a/stb_connected_components.h b/stb_connected_components.h index c3b6886..57fa55c 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -33,7 +33,7 @@ // - better API documentation // - more comments // - try re-integrating naive algorithm & compare performance -// - more optimized batching (current approach still recomputes clumps many times) +// - more optimized batching (current approach still recomputes local clumps many times) // - function for setting a grid of squares at once (just use batching) // - shrink data by storing only, say, 2X max exits // (instead of max exits per clump), and repack cluster diff --git a/tests/stb.dsp b/tests/stb.dsp index bc4cf60..eff7541 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /GX /Z7 /O2 /Ob2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "TT_TEST" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /GX /Z7 /O2 /Ob2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "GRID_TEST" /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe From 1d6e55ab1e2b39f9fcca194022dd98875b07d967 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 12:32:40 -0700 Subject: [PATCH 325/522] reduce storage for stb_connected_components.h --- stb_connected_components.h | 203 ++++++++++++++++++++++++++++++------- 1 file changed, 167 insertions(+), 36 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index 2ba78a3..4130648 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -41,7 +41,6 @@ #define INCLUDE_STB_CONNECTED_COMPONENTS_H #include -#include typedef struct st_stbcc_grid stbcc_grid; @@ -94,6 +93,9 @@ extern unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y); #ifdef STB_CONNECTED_COMPONENTS_IMPLEMENTATION +#include +#include // memset + #if !defined(STBCC_GRID_COUNT_X_LOG2) || !defined(STBCC_GRID_COUNT_Y_LOG2) #error "You must define STBCC_GRID_COUNT_X_LOG2 and STBCC_GRID_COUNT_Y_LOG2 to define the max grid supported." #endif @@ -140,9 +142,22 @@ extern unsigned int stbcc_get_unique_id(stbcc_grid *g, int x, int y); typedef unsigned short stbcc__clumpid; typedef unsigned char stbcc__verify_max_clumps[STBCC__MAX_CLUMPS_PER_CLUSTER < (1 << (8*sizeof(stbcc__clumpid))) ? 1 : -1]; -#define STBCC__MAX_EXITS_PER_CLUMP (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 +#define STBCC__MAX_EXITS_PER_CLUSTER (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 for 32x32 +#define STBCC__MAX_EXITS_PER_CLUMP (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 for 32x32 // 2^19 * 2^6 => 2^25 exits => 2^26 => 64MB for 1024x1024 +// Logic for above on 4x4 grid: +// +// Many clumps: One clump: +// + + + + +// +X.X. +XX.X+ +// .X.X+ .XXX +// +X.X. XXX. +// .X.X+ +X.XX+ +// + + + + +// +// 8 exits either way + typedef unsigned char stbcc__verify_max_exits[STBCC__MAX_EXITS_PER_CLUMP <= 256]; typedef struct @@ -168,15 +183,20 @@ typedef union typedef struct { - stbcc__global_clumpid global_label; - unsigned short num_adjacent; - stbcc__relative_clumpid adjacent_clumps[STBCC__MAX_EXITS_PER_CLUMP]; -} stbcc__clump; + stbcc__global_clumpid global_label; // 4 + unsigned char num_adjacent; // 1 + unsigned char max_adjacent; // 1 + unsigned char adjacent_clump_list_index; // 1 + unsigned char on_edge; // 1 +} stbcc__clump; // 8 +#define STBCC__CLUSTER_ADJACENCY_COUNT (STBCC__MAX_EXITS_PER_CLUSTER*4) typedef struct { unsigned int num_clumps; - stbcc__clump clump[STBCC__MAX_CLUMPS_PER_CLUSTER]; + unsigned char rebuild; + stbcc__clump clump[STBCC__MAX_CLUMPS_PER_CLUSTER]; // 8 * 2^9 = 4KB + stbcc__relative_clumpid adjacency_storage[STBCC__CLUSTER_ADJACENCY_COUNT]; // 512 bytes } stbcc__cluster; struct st_stbcc_grid @@ -184,7 +204,7 @@ struct st_stbcc_grid int w,h,cw,ch; unsigned char map[STBCC__GRID_COUNT_Y][STBCC__MAP_STRIDE]; // 1K x 1K => 1K x 128 => 128KB stbcc__clumpid clump_for_node[STBCC__GRID_COUNT_Y][STBCC__GRID_COUNT_X]; // 1K x 1K x 2 = 2MB - stbcc__cluster cluster[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // 1K x 1K x 0.5 x 64 x 2 = 64MB + stbcc__cluster cluster[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // 1K x 4.5KB = 9MB }; int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) @@ -291,13 +311,15 @@ static void stbcc__build_connected_components_for_clumps(stbcc_grid *g) for (k=0; k < (int) cluster->num_clumps; ++k) { stbcc__clump *clump = &cluster->clump[k]; stbcc__unpacked_clumpid m; + stbcc__relative_clumpid *adj; m.clump_index = k; m.cluster_x = i; m.cluster_y = j; + adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; for (h=0; h < clump->num_adjacent; ++h) { - unsigned int clump_index = clump->adjacent_clumps[h].clump_index; - unsigned int x = clump->adjacent_clumps[h].cluster_dx + i; - unsigned int y = clump->adjacent_clumps[h].cluster_dy + j; + unsigned int clump_index = adj[h].clump_index; + unsigned int x = adj[h].cluster_dx + i; + unsigned int y = adj[h].cluster_dy + j; stbcc__clump_union(g, m, x, y, clump_index); } } @@ -318,6 +340,106 @@ static void stbcc__build_connected_components_for_clumps(stbcc_grid *g) } } +static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int cy) +{ + // in this particular case, we are fully non-incremental. that means we + // can discover the correct sizes for the arrays, but requires we build + // the data into temporary data structures, or just count the sizes, so + // for simplicity we do the latter + stbcc__cluster *cluster = &g->cluster[cy][cx]; + unsigned char connected[STBCC__MAX_CLUMPS_PER_CLUSTER/8]; + unsigned char num_adj[STBCC__MAX_CLUMPS_PER_CLUSTER] = { 0 }; + int x = cx * STBCC__CLUSTER_SIZE_X; + int y = cy * STBCC__CLUSTER_SIZE_Y; + int step_x, step_y=0, i, j, k, n, m, dx, dy, total; + + g->cluster[cy][cx].rebuild = 0; + + total = 0; + for (m=0; m < 4; ++m) { + switch (m) { + case 0: + dx = 1, dy = 0; + step_x = 0, step_y = 1; + i = STBCC__CLUSTER_SIZE_X-1; + j = 0; + n = STBCC__CLUSTER_SIZE_Y; + break; + case 1: + dx = -1, dy = 0; + i = 0; + j = 0; + step_x = 0; + step_y = 1; + n = STBCC__CLUSTER_SIZE_Y; + break; + case 2: + dy = -1, dx = 0; + i = 0; + j = 0; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + break; + case 3: + dy = 1, dx = 0; + i = 0; + j = STBCC__CLUSTER_SIZE_Y-1; + step_x = 1; + step_y = 0; + n = STBCC__CLUSTER_SIZE_X; + break; + } + + if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) + continue; + + memset(connected, 0, sizeof(connected)); + for (k=0; k < n; ++k) { + if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { + stbcc__clumpid c = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (connected[c>>3] & (1 << (c & 7)))) { + connected[c>>3] |= 1 << (c & 7); + ++num_adj[g->clump_for_node[y+j][x+i]]; + ++total; + } + } + i += step_x; + j += step_y; + } + } + + // decide how to apportion leftover... would be better if we knew WHICH clumps + // were along the edge, but we should compute this at initial time, not above + // to minimize recompoutation + total = 0; + for (i=0; i < (int) cluster->num_clumps; ++i) { + int alloc = num_adj[i]*2; // every cluster gets room for 2x current adjacency + assert(total < 256); // must fit in byte + cluster->clump[i].adjacent_clump_list_index = (unsigned char) total; + cluster->clump[i].max_adjacent = alloc; + cluster->clump[i].num_adjacent = 0; + total += alloc; + } + assert(total <= STBCC__CLUSTER_ADJACENCY_COUNT); + + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, -1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 1, 0); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0,-1); + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0, 1); + // make sure all of the above succeeded. + assert(g->cluster[cy][cx].rebuild == 0); +} + +static void stbcc__add_connections_to_adjacent_cluster_with_rebuild(stbcc_grid *g, int cx, int cy, int dx, int dy) +{ + if (cx >= 0 && cx < g->cw && cy >= 0 && cy < g->ch) { + stbcc__add_connections_to_adjacent_cluster(g, cx, cy, dx, dy); + if (g->cluster[cy][cx].rebuild) + stbcc__build_all_connections_for_cluster(g, cx, cy); + } +} + void stbcc_update_grid(stbcc_grid *g, int x, int y, int solid) { int cx,cy; @@ -344,16 +466,12 @@ void stbcc_update_grid(stbcc_grid *g, int x, int y, int solid) STBCC__MAP_BYTE(g,x,y) &= ~STBCC__MAP_BYTE_MASK(x,y); stbcc__build_clumps_for_cluster(g, cx, cy); + stbcc__build_all_connections_for_cluster(g, cx, cy); - stbcc__add_connections_to_adjacent_cluster(g, cx, cy, -1, 0); - stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 1, 0); - stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0,-1); - stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0, 1); - - stbcc__add_connections_to_adjacent_cluster(g, cx-1, cy, 1, 0); - stbcc__add_connections_to_adjacent_cluster(g, cx+1, cy, -1, 0); - stbcc__add_connections_to_adjacent_cluster(g, cx, cy-1, 0, 1); - stbcc__add_connections_to_adjacent_cluster(g, cx, cy+1, 0,-1); + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx-1, cy, 1, 0); + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx+1, cy, -1, 0); + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx, cy-1, 0, 1); + stbcc__add_connections_to_adjacent_cluster_with_rebuild(g, cx, cy+1, 0,-1); stbcc__build_connected_components_for_clumps(g); } @@ -389,14 +507,9 @@ void stbcc_init_grid(stbcc_grid *g, unsigned char *map, int w, int h) for (i=0; i < g->cw; ++i) stbcc__build_clumps_for_cluster(g, i, j); - for (j=0; j < g->ch; ++j) { - for (i=0; i < g->cw; ++i) { - stbcc__add_connections_to_adjacent_cluster(g, i, j, -1, 0); - stbcc__add_connections_to_adjacent_cluster(g, i, j, 1, 0); - stbcc__add_connections_to_adjacent_cluster(g, i, j, 0,-1); - stbcc__add_connections_to_adjacent_cluster(g, i, j, 0, 1); - } - } + for (j=0; j < g->ch; ++j) + for (i=0; i < g->cw; ++i) + stbcc__build_all_connections_for_cluster(g, i, j); stbcc__build_connected_components_for_clumps(g); @@ -408,6 +521,7 @@ void stbcc_init_grid(stbcc_grid *g, unsigned char *map, int w, int h) static void stbcc__add_clump_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) { + stbcc__cluster *cluster; stbcc__clump *clump; int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); @@ -429,14 +543,22 @@ static void stbcc__add_clump_connection(stbcc_grid *g, int x1, int y1, int x2, i rc.cluster_dx = x2-x1; rc.cluster_dy = y2-y1; - clump = &g->cluster[cy1][cx1].clump[c1]; - assert(clump->num_adjacent < STBCC__MAX_EXITS_PER_CLUMP); - clump->adjacent_clumps[clump->num_adjacent++] = rc; + cluster = &g->cluster[cy1][cx1]; + clump = &cluster->clump[c1]; + if (clump->num_adjacent == clump->max_adjacent) + g->cluster[cy1][cx1].rebuild = 1; + else { + stbcc__relative_clumpid *adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; + assert(clump->num_adjacent < STBCC__MAX_EXITS_PER_CLUMP); + adj[clump->num_adjacent++] = rc; + } } static void stbcc__remove_clump_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) { + stbcc__cluster *cluster; stbcc__clump *clump; + stbcc__relative_clumpid *adj; int i; int cx1 = STBCC__CLUSTER_X_FOR_COORD_X(x1); @@ -458,16 +580,18 @@ static void stbcc__remove_clump_connection(stbcc_grid *g, int x1, int y1, int x2 rc.cluster_dx = x2-x1; rc.cluster_dy = y2-y1; - clump = &g->cluster[cy1][cx1].clump[c1]; + cluster = &g->cluster[cy1][cx1]; + clump = &cluster->clump[c1]; + adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; for (i=0; i < clump->num_adjacent; ++i) - if (rc.clump_index == clump->adjacent_clumps[i].clump_index && - rc.cluster_dx == clump->adjacent_clumps[i].cluster_dx && - rc.cluster_dy == clump->adjacent_clumps[i].cluster_dy) + if (rc.clump_index == adj[i].clump_index && + rc.cluster_dx == adj[i].cluster_dx && + rc.cluster_dy == adj[i].cluster_dy) break; if (i < clump->num_adjacent) - clump->adjacent_clumps[i] = clump->adjacent_clumps[--clump->num_adjacent]; + adj[i] = adj[--clump->num_adjacent]; else assert(0); } @@ -485,6 +609,9 @@ static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, in if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) return; + if (g->cluster[cy][cx].rebuild) + return; + assert(abs(dx) + abs(dy) == 1); if (dx == 1) { @@ -521,6 +648,8 @@ static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, in if (0 == (connected[c>>3] & (1 << (c & 7)))) { connected[c>>3] |= 1 << (c & 7); stbcc__add_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); + if (g->cluster[cy][cx].rebuild) + break; } } i += step_x; @@ -669,6 +798,8 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) g->clump_for_node[y+j][x+i] = cbi.label[j][i]; // @OPTIMIZE: remove cbi.label entirely assert(g->clump_for_node[y+j][x+i] <= STBCC__NULL_CLUMPID); } + + c->rebuild = 1; // flag that it has no valid data } #endif // STB_CONNECTED_COMPONENTS_IMPLEMENTATION From 667f79589a2475a97839dbd0f5c1c2a4392c22b1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 12:58:37 -0700 Subject: [PATCH 326/522] forgot to include stb_connected_components test source file --- tests/grid_reachability.c | 260 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 tests/grid_reachability.c diff --git a/tests/grid_reachability.c b/tests/grid_reachability.c new file mode 100644 index 0000000..1db4b08 --- /dev/null +++ b/tests/grid_reachability.c @@ -0,0 +1,260 @@ +#define STB_CONNECTED_COMPONENTS_IMPLEMENTATION +#define STBCC_GRID_COUNT_X_LOG2 10 +#define STBCC_GRID_COUNT_Y_LOG2 10 +#include "stb_connected_components.h" + +#ifdef GRID_TEST + +#include +#include +#include + +//#define STB_DEFINE +#include "stb.h" + +//#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +//#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +typedef struct +{ + uint16 x,y; +} point; + +point leader[1024][1024]; +uint32 color[1024][1024]; + +point find(int x, int y) +{ + point p,q; + p = leader[y][x]; + if (p.x == x && p.y == y) + return p; + q = find(p.x, p.y); + leader[y][x] = q; + return q; +} + +void onion(int x1, int y1, int x2, int y2) +{ + point p = find(x1,y1); + point q = find(x2,y2); + + if (p.x == q.x && p.y == q.y) + return; + + leader[p.y][p.x] = q; +} + +void reference(uint8 *map, int w, int h) +{ + int i,j; + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + leader[j][i].x = i; + leader[j][i].y = j; + } + } + + for (j=1; j < h-1; ++j) { + for (i=1; i < w-1; ++i) { + if (map[j*w+i] == 255) { + if (map[(j+1)*w+i] == 255) onion(i,j, i,j+1); + if (map[(j)*w+i+1] == 255) onion(i,j, i+1,j); + } + } + } + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + uint32 c = 0xff000000; + if (leader[j][i].x == i && leader[j][i].y == j) { + if (map[j*w+i] == 255) + c = stb_randLCG() | 0xff404040; + } + color[j][i] = c; + } + } + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + if (leader[j][i].x != i || leader[j][i].y != j) { + point p = find(i,j); + color[j][i] = color[p.y][p.x]; + } + } + } +} + +void write_map(stbcc_grid *g, int w, int h, char *filename) +{ + int i,j; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + unsigned int c; + c = stbcc_get_unique_id(g,i,j); + if (c == STBCC_NULL_UNIQUE_ID) + c = 0xff000000; + else + c = ~c; + color[j][i] = c; + } + } + stbi_write_png(filename, w, h, 4, color, 0); +} + +void test_connected(stbcc_grid *g) +{ + int n = stbcc_query_grid_node_connection(g, 512, 90, 512, 871); + //printf("%d ", n); +} + +static char *message; +LARGE_INTEGER start; + +void start_timer(char *s) +{ + message = s; + QueryPerformanceCounter(&start); +} + +void end_timer(void) +{ + LARGE_INTEGER end, freq; + double tm; + + QueryPerformanceCounter(&end); + QueryPerformanceFrequency(&freq); + + tm = (end.QuadPart - start.QuadPart) / (double) freq.QuadPart; + printf("%6.4lf ms: %s\n", tm * 1000, message); +} + +int main(int argc, char **argv) +{ + stbcc_grid *g; + + int w,h, i,j,k=0, count=0; + uint8 *map = stbi_load("data/map_03.png", &w, &h, 0, 1); + + assert(map); + + stbi_write_png("tests/output/stbcc/reference.png", w, h, 1, map, 0); + + for (j=0; j < h; ++j) + for (i=0; i < w; ++i) + map[j*w+i] = ~map[j*w+i]; + + //reference(map, w, h); + + _mkdir("tests/output/stbcc"); + + g = malloc(stbcc_grid_sizeof()); + printf("Size: %d\n", stbcc_grid_sizeof()); + + start_timer("init"); + stbcc_init_grid(g, map, w, h); + end_timer(); + write_map(g, w, h, "tests/output/stbcc/base.png"); + + printf("Cluster size: %d,%d\n", STBCC__CLUSTER_SIZE_X, STBCC__CLUSTER_SIZE_Y); + + #if 1 + start_timer("removing"); + count = 0; + for (i=0; i < 1800; ++i) { + int x,y,a,b; + x = stb_rand() % (w-32); + y = stb_rand() % (h-32); + + if (i & 1) { + for (a=0; a < 32; ++a) + for (b=0; b < 1; ++b) + if (stbcc_query_grid_open(g, x+a, y+b)) { + stbcc_update_grid(g, x+a, y+b, 1); + ++count; + } + } else { + for (a=0; a < 1; ++a) + for (b=0; b < 32; ++b) + if (stbcc_query_grid_open(g, x+a, y+b)) { + stbcc_update_grid(g, x+a, y+b, 1); + ++count; + } + } + + //if (i % 100 == 0) write_map(g, w, h, stb_sprintf("tests/output/stbcc/open_random_%d.png", i+1)); + } + end_timer(); + printf("Removed %d grid spaces\n", count); + write_map(g, w, h, stb_sprintf("tests/output/stbcc/open_random_%d.png", i)); + start_timer("adding"); + count = 0; + for (i=0; i < 1800; ++i) { + int x,y,a,b; + x = stb_rand() % (w-32); + y = stb_rand() % (h-32); + + if (i & 1) { + for (a=0; a < 32; ++a) + for (b=0; b < 1; ++b) + if (!stbcc_query_grid_open(g, x+a, y+b)) { + stbcc_update_grid(g, x+a, y+b, 0); + ++count; + } + } else { + for (a=0; a < 1; ++a) + for (b=0; b < 32; ++b) + if (!stbcc_query_grid_open(g, x+a, y+b)) { + stbcc_update_grid(g, x+a, y+b, 0); + ++count; + } + } + + //if (i % 100 == 0) write_map(g, w, h, stb_sprintf("tests/output/stbcc/close_random_%d.png", i+1)); + } + end_timer(); + write_map(g, w, h, stb_sprintf("tests/output/stbcc/close_random_%d.png", i)); + printf("Added %d grid spaces\n", count); + #endif + + #if 0 // for map_02.png + start_timer("process"); + for (k=0; k < 20; ++k) { + for (j=0; j < h; ++j) { + int any=0; + for (i=0; i < w; ++i) { + if (map[j*w+i] > 10 && map[j*w+i] < 250) { + //start_timer(stb_sprintf("open %d,%d", i,j)); + stbcc_update_grid(g, i, j, 0); + test_connected(g); + //end_timer(); + any = 1; + } + } + if (any) write_map(g, w, h, stb_sprintf("tests/output/stbcc/open_row_%04d.png", j)); + } + + for (j=0; j < h; ++j) { + int any=0; + for (i=0; i < w; ++i) { + if (map[j*w+i] > 10 && map[j*w+i] < 250) { + //start_timer(stb_sprintf("close %d,%d", i,j)); + stbcc_update_grid(g, i, j, 1); + test_connected(g); + //end_timer(); + any = 1; + } + } + if (any) write_map(g, w, h, stb_sprintf("tests/output/stbcc/close_row_%04d.png", j)); + } + } + end_timer(); + #endif + + return 0; +} +#endif From ad55a9b383dd7dc9846a303c2e0a56a719fab2b7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 14:05:40 -0700 Subject: [PATCH 327/522] version 0.93 assign surplus adjacency storage only to clumps that touch edge document timings and memory usage --- stb_connected_components.h | 162 +++++++++++++++++++++++++------------ tests/grid_reachability.c | 37 ++++++++- 2 files changed, 145 insertions(+), 54 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index 8531dd6..1533b30 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -1,4 +1,4 @@ -// stb_connected_components - v0.91 - public domain connected components on grids +// stb_connected_components - v0.93 - public domain connected components on grids // http://github.com/nothings/stb // // Finds connected components on 2D grids for testing reachability between @@ -15,17 +15,25 @@ // #include "stb_connected_components.h" // // The above creates an implementation that can run on maps up to 1024x1024. -// Map sizes must be a multiple of 32 on each axis. +// Map sizes must be a multiple of (1<<(LOG2/2)) on each axis (e.g. 32 if LOG2=10, +// 16 if LOG2=8, etc.) (You can just pad your map with untraversable space.) // -// LICENSE -// -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// MEMORY USAGE // +// Uses about 6-7 bytes per grid square (e.g. 7MB for a 1024x1024 grid). +// +// PERFORMANCE +// +// On a core i7-2700K at 3.5 Ghz, for a particular 1024x1024 map (map_03.png): +// +// Creating map : 44.85 ms +// Making one square traversable: 0.27 ms (average over 29,448 calls) +// Making one square untraversable: 0.23 ms (average over 30,123 calls) +// Reachability query: 0.00001 ms (average over 4,000,000 calls) // // CHANGELOG // +// 0.93 (2016-04-16) Reduce memory by 10x for 1Kx1K map; small speedup // 0.92 (2016-04-16) Compute sqrt(N) cluster size by default // 0.91 (2016-04-15) Initial release // @@ -35,38 +43,37 @@ // - try re-integrating naive algorithm & compare performance // - more optimized batching (current approach still recomputes local clumps many times) // - function for setting a grid of squares at once (just use batching) -// - shrink data by storing only, say, 2X max exits -// (instead of max exits per clump), and repack cluster -// if it runs out (possibly by just rebuilding from scratch, -// could even use dirty-cluster data structure) -// should reduce 1Kx1K from ~66MB to ~8MB // -// ALGORITHM +// LICENSE +// +// This software is dual-licensed to the public domain and under the following +// license: you are granted a perpetual, irrevocable license to copy, modify, +// publish, and distribute this file as you see fit. // -// The NxN grid map is split into sqrt(N) x sqrt(N) blocks called -// "clusters". Each cluster independently computes a set of connected -// components within that cluster (ignoring all connectivity out of -// that cluster) using a union-find disjoint set forest. This produces a bunch -// of locally connected components called "clumps". Each clump is (a) connected -// within its cluster, (b) does not directly connect to any other clumps in the -// cluster (though it may connect to them by paths that lead outside the cluster, -// but those are ignored at this step), and (c) maintains an adjacency list of -// all clumps in adjacent clusters that it _is_ connected to. Then a second -// union-find disjoint set forest is used to compute connected clumps -// globally, across the whole map. Reachability is then computed by -// finding which clump each input point belongs to, and checking whether -// those clumps are in the same "global" connected component. +// ALGORITHM // -// The above data structure can be updated efficiently; on a change -// of a single grid square on the map, only one cluster changes its -// purely-local state, so only one cluster needs its clumps fully -// recomputed. Clumps in adjacent clusters need their adjacency lists -// updated: first to remove all references to the old clumps in the -// rebuilt cluster, then to add new references to the new clumps. Both -// of these operations can use the existing "find which clump each input -// point belongs to" query to compute that adjacency information rapidly. -// In one 1024x1024 test on a specific machine, a one-tile update was -// about 250 times faster than a full disjoint-set-forest on the full map. +// The NxN grid map is split into sqrt(N) x sqrt(N) blocks called +// "clusters". Each cluster independently computes a set of connected +// components within that cluster (ignoring all connectivity out of +// that cluster) using a union-find disjoint set forest. This produces a bunch +// of locally connected components called "clumps". Each clump is (a) connected +// within its cluster, (b) does not directly connect to any other clumps in the +// cluster (though it may connect to them by paths that lead outside the cluster, +// but those are ignored at this step), and (c) maintains an adjacency list of +// all clumps in adjacent clusters that it _is_ connected to. Then a second +// union-find disjoint set forest is used to compute connected clumps +// globally, across the whole map. Reachability is then computed by +// finding which clump each input point belongs to, and checking whether +// those clumps are in the same "global" connected component. +// +// The above data structure can be updated efficiently; on a change +// of a single grid square on the map, only one cluster changes its +// purely-local state, so only one cluster needs its clumps fully +// recomputed. Clumps in adjacent clusters need their adjacency lists +// updated: first to remove all references to the old clumps in the +// rebuilt cluster, then to add new references to the new clumps. Both +// of these operations can use the existing "find which clump each input +// point belongs to" query to compute that adjacency information rapidly. #ifndef INCLUDE_STB_CONNECTED_COMPONENTS_H #define INCLUDE_STB_CONNECTED_COMPONENTS_H @@ -235,13 +242,14 @@ typedef struct unsigned char on_edge; // 1 } stbcc__clump; // 8 -#define STBCC__CLUSTER_ADJACENCY_COUNT (STBCC__MAX_EXITS_PER_CLUSTER*4) +#define STBCC__CLUSTER_ADJACENCY_COUNT (STBCC__MAX_EXITS_PER_CLUSTER*2) typedef struct { - unsigned int num_clumps; - unsigned char rebuild; + short num_clumps; + unsigned char num_edge_clumps; + unsigned char rebuild_adjacency; stbcc__clump clump[STBCC__MAX_CLUMPS_PER_CLUSTER]; // 8 * 2^9 = 4KB - stbcc__relative_clumpid adjacency_storage[STBCC__CLUSTER_ADJACENCY_COUNT]; // 512 bytes + stbcc__relative_clumpid adjacency_storage[STBCC__CLUSTER_ADJACENCY_COUNT]; // 256 bytes } stbcc__cluster; struct st_stbcc_grid @@ -251,7 +259,7 @@ struct st_stbcc_grid //unsigned char cluster_dirty[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // could bitpack, but: 1K x 1K => 1KB unsigned char map[STBCC__GRID_COUNT_Y][STBCC__MAP_STRIDE]; // 1K x 1K => 1K x 128 => 128KB stbcc__clumpid clump_for_node[STBCC__GRID_COUNT_Y][STBCC__GRID_COUNT_X]; // 1K x 1K x 2 = 2MB - stbcc__cluster cluster[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // 1K x 4.5KB = 9MB + stbcc__cluster cluster[STBCC__CLUSTER_COUNT_Y][STBCC__CLUSTER_COUNT_X]; // 1K x 4.5KB = 4.5MB }; int stbcc_query_grid_node_connection(stbcc_grid *g, int x1, int y1, int x2, int y2) @@ -402,8 +410,9 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int int x = cx * STBCC__CLUSTER_SIZE_X; int y = cy * STBCC__CLUSTER_SIZE_Y; int step_x, step_y=0, i, j, k, n, m, dx, dy, total; + int extra; - g->cluster[cy][cx].rebuild = 0; + g->cluster[cy][cx].rebuild_adjacency = 0; total = 0; for (m=0; m < 4; ++m) { @@ -459,12 +468,36 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int } } - // decide how to apportion leftover... would be better if we knew WHICH clumps - // were along the edge, but we should compute this at initial time, not above - // to minimize recompoutation + assert(total <= STBCC__CLUSTER_ADJACENCY_COUNT); + + // decide how to apportion unused adjacency slots; only clumps that lie + // on the edges of the cluster need adjacency slots, so divide them up + // evenly between those clumps + + // we want: + // extra = (STBCC__CLUSTER_ADJACENCY_COUNT - total) / cluster->num_edge_clumps; + // but we efficiently approximate this without a divide, because + // ignoring edge-vs-non-edge with 'num_adj[i]*2' was faster than + // 'num_adj[i]+extra' with the divide + if (total + (cluster->num_edge_clumps<<2) <= STBCC__CLUSTER_ADJACENCY_COUNT) + extra = 4; + else if (total + (cluster->num_edge_clumps<<1) <= STBCC__CLUSTER_ADJACENCY_COUNT) + extra = 2; + else if (total + (cluster->num_edge_clumps<<0) <= STBCC__CLUSTER_ADJACENCY_COUNT) + extra = 1; + else + extra = 0; + total = 0; for (i=0; i < (int) cluster->num_clumps; ++i) { - int alloc = num_adj[i]*2; // every cluster gets room for 2x current adjacency + int alloc=0; + if (cluster->clump[i].on_edge) { + alloc = num_adj[i]+extra; + if (alloc > STBCC__MAX_EXITS_PER_CLUSTER) + alloc = STBCC__MAX_EXITS_PER_CLUSTER; + } + else + assert(num_adj[i] == 0); assert(total < 256); // must fit in byte cluster->clump[i].adjacent_clump_list_index = (unsigned char) total; cluster->clump[i].max_adjacent = alloc; @@ -478,14 +511,14 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0,-1); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0, 1); // make sure all of the above succeeded. - assert(g->cluster[cy][cx].rebuild == 0); + assert(g->cluster[cy][cx].rebuild_adjacency == 0); } static void stbcc__add_connections_to_adjacent_cluster_with_rebuild(stbcc_grid *g, int cx, int cy, int dx, int dy) { if (cx >= 0 && cx < g->cw && cy >= 0 && cy < g->ch) { stbcc__add_connections_to_adjacent_cluster(g, cx, cy, dx, dy); - if (g->cluster[cy][cx].rebuild) + if (g->cluster[cy][cx].rebuild_adjacency) stbcc__build_all_connections_for_cluster(g, cx, cy); } } @@ -621,7 +654,7 @@ static void stbcc__add_clump_connection(stbcc_grid *g, int x1, int y1, int x2, i cluster = &g->cluster[cy1][cx1]; clump = &cluster->clump[c1]; if (clump->num_adjacent == clump->max_adjacent) - g->cluster[cy1][cx1].rebuild = 1; + g->cluster[cy1][cx1].rebuild_adjacency = 1; else { stbcc__relative_clumpid *adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; assert(clump->num_adjacent < STBCC__MAX_EXITS_PER_CLUMP); @@ -684,7 +717,7 @@ static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, in if (cx+dx < 0 || cx+dx >= g->cw || cy+dy < 0 || cy+dy >= g->ch) return; - if (g->cluster[cy][cx].rebuild) + if (g->cluster[cy][cx].rebuild_adjacency) return; assert(abs(dx) + abs(dy) == 1); @@ -723,7 +756,7 @@ static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, in if (0 == (connected[c>>3] & (1 << (c & 7)))) { connected[c>>3] |= 1 << (c & 7); stbcc__add_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); - if (g->cluster[cy][cx].rebuild) + if (g->cluster[cy][cx].rebuild_adjacency) break; } } @@ -815,7 +848,7 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) stbcc__cluster *c; stbcc__cluster_build_info cbi; int label=0; - int i,j; + int i,j, num_on_edge; int x = cx * STBCC__CLUSTER_SIZE_X; int y = cy * STBCC__CLUSTER_SIZE_Y; @@ -874,7 +907,30 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) assert(g->clump_for_node[y+j][x+i] <= STBCC__NULL_CLUMPID); } - c->rebuild = 1; // flag that it has no valid data + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + int d = cbi.label[0][i]; + if (d != STBCC__NULL_CLUMPID) + c->clump[d].on_edge = 1; + d = cbi.label[STBCC__CLUSTER_SIZE_Y-1][i]; + if (d != STBCC__NULL_CLUMPID) + c->clump[d].on_edge = 1; + } + + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + int d = cbi.label[j][0]; + if (d != STBCC__NULL_CLUMPID) + c->clump[d].on_edge = 1; + d = cbi.label[j][STBCC__CLUSTER_SIZE_X-1]; + if (d != STBCC__NULL_CLUMPID) + c->clump[d].on_edge = 1; + } + + num_on_edge = 0; + for (i=0; i < (int) c->num_clumps; ++i) + num_on_edge += c->clump[i].on_edge; + c->num_edge_clumps = num_on_edge; + + c->rebuild_adjacency = 1; // flag that it has no valid adjacency data } #endif // STB_CONNECTED_COMPONENTS_IMPLEMENTATION diff --git a/tests/grid_reachability.c b/tests/grid_reachability.c index 1db4b08..c1c49b7 100644 --- a/tests/grid_reachability.c +++ b/tests/grid_reachability.c @@ -133,11 +133,12 @@ void end_timer(void) printf("%6.4lf ms: %s\n", tm * 1000, message); } +int loc[5000][2]; int main(int argc, char **argv) { stbcc_grid *g; - int w,h, i,j,k=0, count=0; + int w,h, i,j,k=0, count=0, r; uint8 *map = stbi_load("data/map_03.png", &w, &h, 0, 1); assert(map); @@ -160,6 +161,25 @@ int main(int argc, char **argv) end_timer(); write_map(g, w, h, "tests/output/stbcc/base.png"); + for (i=0; i < 5000;) { + loc[i][0] = stb_rand() % w; + loc[i][1] = stb_rand() % h; + if (stbcc_query_grid_open(g, loc[i][0], loc[i][1])) + ++i; + } + + r = 0; + start_timer("reachable"); + for (i=0; i < 2000; ++i) { + for (j=0; j < 2000; ++j) { + int x1 = loc[i][0], y1 = loc[i][1]; + int x2 = loc[2000+j][0], y2 = loc[2000+j][1]; + r += stbcc_query_grid_node_connection(g, x1,y1, x2,y2); + } + } + end_timer(); + printf("%d reachable\n", r); + printf("Cluster size: %d,%d\n", STBCC__CLUSTER_SIZE_X, STBCC__CLUSTER_SIZE_Y); #if 1 @@ -191,6 +211,20 @@ int main(int argc, char **argv) end_timer(); printf("Removed %d grid spaces\n", count); write_map(g, w, h, stb_sprintf("tests/output/stbcc/open_random_%d.png", i)); + + + r = 0; + start_timer("reachable"); + for (i=0; i < 1000; ++i) { + for (j=0; j < 1000; ++j) { + int x1 = loc[i][0], y1 = loc[i][1]; + int x2 = loc[j][0], y2 = loc[j][1]; + r += stbcc_query_grid_node_connection(g, x1,y1, x2,y2); + } + } + end_timer(); + printf("%d reachable\n", r); + start_timer("adding"); count = 0; for (i=0; i < 1800; ++i) { @@ -221,6 +255,7 @@ int main(int argc, char **argv) printf("Added %d grid spaces\n", count); #endif + #if 0 // for map_02.png start_timer("process"); for (k=0; k < 20; ++k) { From 5ebbfd02e96779112569a0ac7ee74e4b74512ac3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 14:08:03 -0700 Subject: [PATCH 328/522] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a7c7e01..6c5bfd6 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ library | lastest version | category | LoC | description **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**stb_connected_comp...** | 0.91 | misc | 674 | incrementally compute reachability on grids +**stb_connected_comp...** | 0.93 | misc | 936 | incrementally compute reachability on grids **stb.h** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 -Total lines of C code: 47488 +Total lines of C code: 47750 FAQ From 484605343fa12cf83532d3261a14b56fb1060e86 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Apr 2016 14:14:04 -0700 Subject: [PATCH 329/522] memory usage clarification --- stb_connected_components.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_connected_components.h b/stb_connected_components.h index 1533b30..f72c151 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -21,6 +21,7 @@ // MEMORY USAGE // // Uses about 6-7 bytes per grid square (e.g. 7MB for a 1024x1024 grid). +// Uses a single worst-case allocation which you pass in. // // PERFORMANCE // From d1eba3330529205c33fee6a8ac5242f8d87f0ccc Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 17 Apr 2016 08:12:52 -0700 Subject: [PATCH 330/522] fix bug w/ large clumps per cluster; reduce time spent on global union-find by skipping clumps that don't touch edges --- stb_connected_components.h | 120 +++++++++++++++++++++++++++++++++---- tests/grid_reachability.c | 26 +++++++- 2 files changed, 133 insertions(+), 13 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index f72c151..afa44fc 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -353,7 +353,7 @@ static void stbcc__build_connected_components_for_clumps(stbcc_grid *g) for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { stbcc__cluster *cluster = &g->cluster[j][i]; - for (k=0; k < (int) cluster->num_clumps; ++k) { + for (k=0; k < (int) cluster->num_edge_clumps; ++k) { stbcc__global_clumpid m; m.f.clump_index = k; m.f.cluster_x = i; @@ -367,7 +367,7 @@ static void stbcc__build_connected_components_for_clumps(stbcc_grid *g) for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { stbcc__cluster *cluster = &g->cluster[j][i]; - for (k=0; k < (int) cluster->num_clumps; ++k) { + for (k=0; k < (int) cluster->num_edge_clumps; ++k) { stbcc__clump *clump = &cluster->clump[k]; stbcc__unpacked_clumpid m; stbcc__relative_clumpid *adj; @@ -388,7 +388,7 @@ static void stbcc__build_connected_components_for_clumps(stbcc_grid *g) for (j=0; j < STBCC__CLUSTER_COUNT_Y; ++j) { for (i=0; i < STBCC__CLUSTER_COUNT_X; ++i) { stbcc__cluster *cluster = &g->cluster[j][i]; - for (k=0; k < (int) cluster->num_clumps; ++k) { + for (k=0; k < (int) cluster->num_edge_clumps; ++k) { stbcc__global_clumpid m; m.f.clump_index = k; m.f.cluster_x = i; @@ -507,10 +507,15 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int } assert(total <= STBCC__CLUSTER_ADJACENCY_COUNT); + assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, -1, 0); + assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 1, 0); + assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0,-1); + assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0, 1); + assert(g->w); // make sure all of the above succeeded. assert(g->cluster[cy][cx].rebuild_adjacency == 0); } @@ -654,11 +659,13 @@ static void stbcc__add_clump_connection(stbcc_grid *g, int x1, int y1, int x2, i cluster = &g->cluster[cy1][cx1]; clump = &cluster->clump[c1]; + assert(clump->num_adjacent <= clump->max_adjacent); if (clump->num_adjacent == clump->max_adjacent) g->cluster[cy1][cx1].rebuild_adjacency = 1; else { stbcc__relative_clumpid *adj = &cluster->adjacency_storage[clump->adjacent_clump_list_index]; assert(clump->num_adjacent < STBCC__MAX_EXITS_PER_CLUMP); + assert(clump->adjacent_clump_list_index + clump->num_adjacent <= STBCC__CLUSTER_ADJACENCY_COUNT); adj[clump->num_adjacent++] = rc; } } @@ -755,6 +762,7 @@ static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, in if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { stbcc__clumpid c = g->clump_for_node[y+j+dy][x+i+dx]; if (0 == (connected[c>>3] & (1 << (c & 7)))) { + assert((c>>3) < sizeof(connected)); connected[c>>3] |= 1 << (c & 7); stbcc__add_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); if (g->cluster[cy][cx].rebuild_adjacency) @@ -844,6 +852,14 @@ static void stbcc__incluster_union(stbcc__cluster_build_info *cbi, int x1, int y cbi->parent[p.y][p.x] = q; } +static void stbcc__switch_root(stbcc__cluster_build_info *cbi, int x, int y, stbcc__tinypoint p) +{ + cbi->parent[p.y][p.x].x = x; + cbi->parent[p.y][p.x].y = y; + cbi->parent[y][x].x = x; + cbi->parent[y][x].y = y; +} + static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) { stbcc__cluster *c; @@ -874,9 +890,69 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) stbcc__incluster_union(&cbi, i,j, i+1,j); } - // label all non-empty leaders + // label all non-empty clumps along edges so that all edge clumps are first + // in list; this means in degenerate case we can skip traversing non-edge clumps. + // because in the first pass we only label leaders, we swap the leader to the + // edge first + + // first put solid labels on all the edges; these will get overwritten if they're open + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) + cbi.label[j][0] = cbi.label[j][STBCC__CLUSTER_SIZE_X-1] = STBCC__NULL_CLUMPID; + for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) + cbi.label[0][i] = cbi.label[STBCC__CLUSTER_SIZE_Y-1][i] = STBCC__NULL_CLUMPID; + for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { - for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { + i = 0; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + // if this is the leader, give it a label + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + // if leader is in interior, promote this edge node to leader and label + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + // else if leader is on edge, do nothing (it'll get labelled when we reach it) + } + i = STBCC__CLUSTER_SIZE_X-1; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + } + } + + for (i=1; i < STBCC__CLUSTER_SIZE_Y-1; ++i) { + j = 0; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + } + j = STBCC__CLUSTER_SIZE_Y-1; + if (STBCC__MAP_OPEN(g, x+i, y+j)) { + stbcc__tinypoint p = stbcc__incluster_find(&cbi, i,j); + if (p.x == i && p.y == j) + cbi.label[j][i] = label++; + else if (!(p.x == 0 || p.x == STBCC__CLUSTER_SIZE_X-1 || p.y == 0 || p.y == STBCC__CLUSTER_SIZE_Y-1)) { + stbcc__switch_root(&cbi, i, j, p); + cbi.label[j][i] = label++; + } + } + } + + // label any internal clusters + for (j=1; j < STBCC__CLUSTER_SIZE_Y-1; ++j) { + for (i=1; i < STBCC__CLUSTER_SIZE_X-1; ++i) { stbcc__tinypoint p = cbi.parent[j][i]; if (p.x == i && p.y == j) if (STBCC__MAP_OPEN(g,x+i,y+j)) @@ -894,13 +970,17 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) if (STBCC__MAP_OPEN(g,x+i,y+j)) cbi.label[j][i] = cbi.label[p.y][p.x]; } + if (STBCC__MAP_OPEN(g,x+i,y+j)) + assert(cbi.label[j][i] != STBCC__NULL_CLUMPID); } } c = &g->cluster[cy][cx]; c->num_clumps = label; - for (i=0; i < label; ++i) + for (i=0; i < label; ++i) { c->clump[i].num_adjacent = 0; + c->clump[i].on_edge = 0; + } for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { @@ -910,20 +990,24 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { int d = cbi.label[0][i]; - if (d != STBCC__NULL_CLUMPID) + if (d != STBCC__NULL_CLUMPID) { c->clump[d].on_edge = 1; + } d = cbi.label[STBCC__CLUSTER_SIZE_Y-1][i]; - if (d != STBCC__NULL_CLUMPID) + if (d != STBCC__NULL_CLUMPID) { c->clump[d].on_edge = 1; + } } - for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) { + for (j=1; j < STBCC__CLUSTER_SIZE_Y-1; ++j) { int d = cbi.label[j][0]; - if (d != STBCC__NULL_CLUMPID) + if (d != STBCC__NULL_CLUMPID) { c->clump[d].on_edge = 1; + } d = cbi.label[j][STBCC__CLUSTER_SIZE_X-1]; - if (d != STBCC__NULL_CLUMPID) + if (d != STBCC__NULL_CLUMPID) { c->clump[d].on_edge = 1; + } } num_on_edge = 0; @@ -931,6 +1015,20 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) num_on_edge += c->clump[i].on_edge; c->num_edge_clumps = num_on_edge; + for (i=0; i < (int) c->num_edge_clumps; ++i) + assert(c->clump[i].on_edge); + for (; i < (int) c->num_clumps; ++i) + assert(!c->clump[i].on_edge); + + // set the global label for all interior clumps since they can't have connections, so we don't have to do this on the global pass + for (i=(int) c->num_edge_clumps; i < (int) c->num_clumps; ++i) { + stbcc__global_clumpid gc; + gc.f.cluster_x = cx; + gc.f.cluster_y = cy; + gc.f.clump_index = i; + c->clump[i].global_label = gc; + } + c->rebuild_adjacency = 1; // flag that it has no valid adjacency data } diff --git a/tests/grid_reachability.c b/tests/grid_reachability.c index c1c49b7..cb7ff07 100644 --- a/tests/grid_reachability.c +++ b/tests/grid_reachability.c @@ -143,12 +143,16 @@ int main(int argc, char **argv) assert(map); - stbi_write_png("tests/output/stbcc/reference.png", w, h, 1, map, 0); - for (j=0; j < h; ++j) for (i=0; i < w; ++i) map[j*w+i] = ~map[j*w+i]; + for (i=0; i < w; ++i) + for (j=0; j < h; ++j) + map[j*w+i] = (i ^ j) & 1 ? 255 : 0; + + stbi_write_png("tests/output/stbcc/reference.png", w, h, 1, map, 0); + //reference(map, w, h); _mkdir("tests/output/stbcc"); @@ -183,6 +187,24 @@ int main(int argc, char **argv) printf("Cluster size: %d,%d\n", STBCC__CLUSTER_SIZE_X, STBCC__CLUSTER_SIZE_Y); #if 1 + for (j=0; j < 10; ++j) { + for (i=0; i < 5000; ++i) { + loc[i][0] = stb_rand() % w; + loc[i][1] = stb_rand() % h; + } + start_timer("updating 500"); + for (i=0; i < 500; ++i) { + if (stbcc_query_grid_open(g, loc[i][0], loc[i][1])) + stbcc_update_grid(g, loc[i][0], loc[i][1], 1); + else + stbcc_update_grid(g, loc[i][0], loc[i][1], 0); + } + end_timer(); + write_map(g, w, h, stb_sprintf("tests/output/stbcc/update_random_%d.png", j*i)); + } + #endif + + #if 0 start_timer("removing"); count = 0; for (i=0; i < 1800; ++i) { From 51393c0a7a0dcc44e547ce9b774efc6c4c9e0103 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 17 Apr 2016 08:45:06 -0700 Subject: [PATCH 331/522] remove dead code after previous optimizations --- stb_connected_components.h | 62 +++++++------------------------------- tests/grid_reachability.c | 15 ++++++--- 2 files changed, 22 insertions(+), 55 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index afa44fc..3cf9409 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -240,7 +240,7 @@ typedef struct unsigned char num_adjacent; // 1 unsigned char max_adjacent; // 1 unsigned char adjacent_clump_list_index; // 1 - unsigned char on_edge; // 1 + unsigned char reserved; } stbcc__clump; // 8 #define STBCC__CLUSTER_ADJACENCY_COUNT (STBCC__MAX_EXITS_PER_CLUSTER*2) @@ -332,7 +332,6 @@ typedef struct unsigned int clump_index; } stbcc__unpacked_clumpid; -// @OPTIMIZE: pass in these parameters unpacked, not packed static void stbcc__clump_union(stbcc_grid *g, stbcc__unpacked_clumpid m, int x, int y, int idx) { stbcc__clump *mc = &g->cluster[m.cluster_y][m.cluster_x].clump[m.clump_index]; @@ -490,15 +489,10 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int extra = 0; total = 0; - for (i=0; i < (int) cluster->num_clumps; ++i) { - int alloc=0; - if (cluster->clump[i].on_edge) { - alloc = num_adj[i]+extra; - if (alloc > STBCC__MAX_EXITS_PER_CLUSTER) - alloc = STBCC__MAX_EXITS_PER_CLUSTER; - } - else - assert(num_adj[i] == 0); + for (i=0; i < (int) cluster->num_edge_clumps; ++i) { + int alloc = num_adj[i]+extra; + if (alloc > STBCC__MAX_EXITS_PER_CLUSTER) + alloc = STBCC__MAX_EXITS_PER_CLUSTER; assert(total < 256); // must fit in byte cluster->clump[i].adjacent_clump_list_index = (unsigned char) total; cluster->clump[i].max_adjacent = alloc; @@ -507,15 +501,10 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int } assert(total <= STBCC__CLUSTER_ADJACENCY_COUNT); - assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, -1, 0); - assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 1, 0); - assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0,-1); - assert(g->w); stbcc__add_connections_to_adjacent_cluster(g, cx, cy, 0, 1); - assert(g->w); // make sure all of the above succeeded. assert(g->cluster[cy][cx].rebuild_adjacency == 0); } @@ -865,7 +854,7 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) stbcc__cluster *c; stbcc__cluster_build_info cbi; int label=0; - int i,j, num_on_edge; + int i,j; int x = cx * STBCC__CLUSTER_SIZE_X; int y = cy * STBCC__CLUSTER_SIZE_Y; @@ -950,6 +939,9 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) } } + c = &g->cluster[cy][cx]; + c->num_edge_clumps = label; + // label any internal clusters for (j=1; j < STBCC__CLUSTER_SIZE_Y-1; ++j) { for (i=1; i < STBCC__CLUSTER_SIZE_X-1; ++i) { @@ -975,11 +967,11 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) } } - c = &g->cluster[cy][cx]; c->num_clumps = label; + for (i=0; i < label; ++i) { c->clump[i].num_adjacent = 0; - c->clump[i].on_edge = 0; + c->clump[i].max_adjacent = 0; } for (j=0; j < STBCC__CLUSTER_SIZE_Y; ++j) @@ -988,38 +980,6 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) assert(g->clump_for_node[y+j][x+i] <= STBCC__NULL_CLUMPID); } - for (i=0; i < STBCC__CLUSTER_SIZE_X; ++i) { - int d = cbi.label[0][i]; - if (d != STBCC__NULL_CLUMPID) { - c->clump[d].on_edge = 1; - } - d = cbi.label[STBCC__CLUSTER_SIZE_Y-1][i]; - if (d != STBCC__NULL_CLUMPID) { - c->clump[d].on_edge = 1; - } - } - - for (j=1; j < STBCC__CLUSTER_SIZE_Y-1; ++j) { - int d = cbi.label[j][0]; - if (d != STBCC__NULL_CLUMPID) { - c->clump[d].on_edge = 1; - } - d = cbi.label[j][STBCC__CLUSTER_SIZE_X-1]; - if (d != STBCC__NULL_CLUMPID) { - c->clump[d].on_edge = 1; - } - } - - num_on_edge = 0; - for (i=0; i < (int) c->num_clumps; ++i) - num_on_edge += c->clump[i].on_edge; - c->num_edge_clumps = num_on_edge; - - for (i=0; i < (int) c->num_edge_clumps; ++i) - assert(c->clump[i].on_edge); - for (; i < (int) c->num_clumps; ++i) - assert(!c->clump[i].on_edge); - // set the global label for all interior clumps since they can't have connections, so we don't have to do this on the global pass for (i=(int) c->num_edge_clumps; i < (int) c->num_clumps; ++i) { stbcc__global_clumpid gc; diff --git a/tests/grid_reachability.c b/tests/grid_reachability.c index cb7ff07..93667d4 100644 --- a/tests/grid_reachability.c +++ b/tests/grid_reachability.c @@ -99,7 +99,7 @@ void write_map(stbcc_grid *g, int w, int h, char *filename) if (c == STBCC_NULL_UNIQUE_ID) c = 0xff000000; else - c = ~c; + c = (~c)^0x555555; color[j][i] = c; } } @@ -149,7 +149,14 @@ int main(int argc, char **argv) for (i=0; i < w; ++i) for (j=0; j < h; ++j) - map[j*w+i] = (i ^ j) & 1 ? 255 : 0; + map[j*w+i] = (((i+1) ^ (j+1)) >> 1) & 1 ? 255 : 0; + //map[j*w+i] = (((i ^ j) >> 5) ^ (i ^ j)) & 1 ? 255 : 0; + //map[j*w+i] = stb_rand() & 1 ? 255 : 0; + + #if 0 + for (i=0; i < 100000; ++i) + map[(stb_rand()%h)*w + stb_rand()%w] ^= 255; + #endif stbi_write_png("tests/output/stbcc/reference.png", w, h, 1, map, 0); @@ -192,8 +199,8 @@ int main(int argc, char **argv) loc[i][0] = stb_rand() % w; loc[i][1] = stb_rand() % h; } - start_timer("updating 500"); - for (i=0; i < 500; ++i) { + start_timer("updating 2500"); + for (i=0; i < 2500; ++i) { if (stbcc_query_grid_open(g, loc[i][0], loc[i][1])) stbcc_update_grid(g, loc[i][0], loc[i][1], 1); else From 25b1f563d1bfc77750b33ae06cdeb905ae482dbf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 17 Apr 2016 09:16:26 -0700 Subject: [PATCH 332/522] stbcc 0.94 --- stb_connected_components.h | 9 +++++++-- tests/grid_reachability.c | 5 +++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index 3cf9409..abe2d8e 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -1,4 +1,4 @@ -// stb_connected_components - v0.93 - public domain connected components on grids +// stb_connected_components - v0.94 - public domain connected components on grids // http://github.com/nothings/stb // // Finds connected components on 2D grids for testing reachability between @@ -32,8 +32,12 @@ // Making one square untraversable: 0.23 ms (average over 30,123 calls) // Reachability query: 0.00001 ms (average over 4,000,000 calls) // +// On non-degenerate maps update time is O(N^0.5), but on degenerate maps like +// checkerboards or 50% random, update time is O(N^0.75) (~2ms on above machine). +// // CHANGELOG // +// 0.94 (2016-04-17) Bugfix & optimize worst case (checkerboard & random) // 0.93 (2016-04-16) Reduce memory by 10x for 1Kx1K map; small speedup // 0.92 (2016-04-16) Compute sqrt(N) cluster size by default // 0.91 (2016-04-15) Initial release @@ -980,7 +984,8 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) assert(g->clump_for_node[y+j][x+i] <= STBCC__NULL_CLUMPID); } - // set the global label for all interior clumps since they can't have connections, so we don't have to do this on the global pass + // set the global label for all interior clumps since they can't have connections, + // so we don't have to do this on the global pass (brings from O(N) to O(N^0.75)) for (i=(int) c->num_edge_clumps; i < (int) c->num_clumps; ++i) { stbcc__global_clumpid gc; gc.f.cluster_x = cx; diff --git a/tests/grid_reachability.c b/tests/grid_reachability.c index 93667d4..8314d00 100644 --- a/tests/grid_reachability.c +++ b/tests/grid_reachability.c @@ -149,11 +149,12 @@ int main(int argc, char **argv) for (i=0; i < w; ++i) for (j=0; j < h; ++j) - map[j*w+i] = (((i+1) ^ (j+1)) >> 1) & 1 ? 255 : 0; + //map[j*w+i] = (((i+1) ^ (j+1)) >> 1) & 1 ? 255 : 0; + map[j*w+i] = stb_max(abs(i-w/2),abs(j-h/2)) & 1 ? 255 : 0; //map[j*w+i] = (((i ^ j) >> 5) ^ (i ^ j)) & 1 ? 255 : 0; //map[j*w+i] = stb_rand() & 1 ? 255 : 0; - #if 0 + #if 1 for (i=0; i < 100000; ++i) map[(stb_rand()%h)*w + stb_rand()%w] ^= 255; #endif From aa1041bae807d58894b2fa95947d2c01dd591d17 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 17 Apr 2016 09:16:54 -0700 Subject: [PATCH 333/522] stbcc 0.94 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6c5bfd6..c40af5d 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ library | lastest version | category | LoC | description **stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**stb_connected_comp...** | 0.93 | misc | 936 | incrementally compute reachability on grids +**stb_connected_comp...** | 0.94 | misc | 1000 | incrementally compute reachability on grids **stb.h** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 -Total lines of C code: 47750 +Total lines of C code: 47814 FAQ From 376774cb354ced932c10e23705544dbd9d2d88bf Mon Sep 17 00:00:00 2001 From: Thomas Versteeg Date: Tue, 19 Apr 2016 13:24:18 +0200 Subject: [PATCH 334/522] Add @vurtin his nuklear library to other_libs --- docs/other_libs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 27c5130..40f5c43 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -125,7 +125,8 @@ tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing tests | [greatest](https://github.com/silentbicycle/greatest) | iSC | C |**1**| unit testing tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing -user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++*| 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) +user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++*| 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) +user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** | C |**1**| minimal GUI toolkit _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf From 72e10c7e210799ea96d684256445ad687ea50839 Mon Sep 17 00:00:00 2001 From: Thomas Versteeg Date: Tue, 19 Apr 2016 16:01:10 +0200 Subject: [PATCH 335/522] Fix the nuklear library in other_libs.md Change the usable language from C to C/C++ --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 40f5c43..fcb87fb 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -126,7 +126,7 @@ tests | [minctest](https://github.com/codeplea/minctest) tests | [greatest](https://github.com/silentbicycle/greatest) | iSC | C |**1**| unit testing tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++*| 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) -user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** | C |**1**| minimal GUI toolkit +user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** |C/c++|**1**| minimal GUI toolkit _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf From 25b476af56be1e11a5af059e963ca29cb19a0fad Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 19 Apr 2016 07:58:48 -0700 Subject: [PATCH 336/522] Update other_libs.md --- docs/other_libs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index fcb87fb..2fe0432 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -125,8 +125,8 @@ tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing tests | [greatest](https://github.com/silentbicycle/greatest) | iSC | C |**1**| unit testing tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing -user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++*| 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) -user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** |C/c++|**1**| minimal GUI toolkit +user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++ | 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) +user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** |C/C++|**1**| minimal GUI toolkit _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf From e2505ba00c5c0bb1b4c39174052cb78c6202dac8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 19 Apr 2016 09:32:23 -0700 Subject: [PATCH 337/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2fe0432..701e810 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -93,6 +93,7 @@ math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFast math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math math | [PoissonGenerator.h](https://github.com/corporateshark/poisson-disk-generator) | MIT | C++ |**1**| Poisson disk points generator (disk or rect) +math | [prns.h](http://marc-b-reynolds.github.io/shf/2016/04/19/prns.html) | **public domain** |C/C++|**1**| seekable pseudo-random number sequences multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby From f710c23bf7f6b6482e555405f72403a3c3c03167 Mon Sep 17 00:00:00 2001 From: Hansi Raber Date: Fri, 29 Apr 2016 04:45:55 +0200 Subject: [PATCH 338/522] stb_textedit/stb_text_locate_coord: fix cursor position in the "shouldn't happen, but if it does, fall through to end-of-line case" case (`i=0` causes problems with the return values in this case) --- stb_textedit.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 29af484..5a617ea 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -417,10 +417,9 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) // check if it's before the end of the line if (x < r.x1) { // search characters in row for one that straddles 'x' - k = i; prev_x = r.x0; - for (i=0; i < r.num_chars; ++i) { - float w = STB_TEXTEDIT_GETWIDTH(str, k, i); + for (k=0; k < r.num_chars; ++k) { + float w = STB_TEXTEDIT_GETWIDTH(str, i, k); if (x < prev_x+w) { if (x < prev_x+w/2) return k+i; From daecce07d52a6a6759df63826f19afa5b2a893a5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 3 May 2016 13:51:46 -0700 Subject: [PATCH 339/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 701e810..5c36f9e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -36,7 +36,7 @@ as C/C++, as this is not an obstacle to most users.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* -argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | argv parsing +argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | command-line argument parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing From 64270925155c3d40ee8c3cbd54b1affd91594847 Mon Sep 17 00:00:00 2001 From: Dmytro Ivanov Date: Thu, 5 May 2016 01:08:04 +0200 Subject: [PATCH 340/522] tigr now supports osx --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 5c36f9e..ab64b7e 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -72,7 +72,7 @@ geometry math | [yocto_bvh.h](https://github.com/xelatihy/yocto-gl) geometry math | [yocto_shape.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| shape generation, tesselation, normals, etc. geometry math | [yocto_trace.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| physically-based unidirectional path tracer w/ MIS for direct lights graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering -graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows +graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows and OSX graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib |C/C++| 2 | compute tangent space for normal mapping graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering From 5038c23d8f719be5b904955e07f6bfe743c89037 Mon Sep 17 00:00:00 2001 From: Sebastian Steinhauer Date: Thu, 5 May 2016 20:44:49 +0200 Subject: [PATCH 341/522] Added sts_net / sts_mixer to other libraries list --- docs/other_libs.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index ab64b7e..1957fd1 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -39,6 +39,7 @@ AI | [micropather](http://www.grinninglizard.com/MicroPather/) argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | command-line argument parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder +audio |**[sts_mixer](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| simple stereo audio mixer compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/archive/p/fastlz/source/default/source) | MIT |C/C++| 2 | fast but larger LZ compression @@ -96,6 +97,7 @@ math | [PoissonGenerator.h](https://github.com/corporateshark/pois math | [prns.h](http://marc-b-reynolds.github.io/shf/2016/04/19/prns.html) | **public domain** |C/C++|**1**| seekable pseudo-random number sequences multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper +network |**[sts_net](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| cross-platform socket wrapper (socket sets and packet API) network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** |C/C++| 2 | non-production-use http server @@ -134,9 +136,9 @@ _misc_ | [tinyformat](https://github.com/c42f/tinyformat) _misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib |C/C++| 2 | cross-platform debug util libraries _misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | C | 2 | extract English word stems _misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | C | 2 | compute edit distance between two strings - + There are also these XML libraries, but if you're using XML, shame on you: - + - parsing: [tinyxml2](https://github.com/leethomason/tinyxml2): XML - parsing: [pugixml](http://pugixml.org/): XML (MIT license) @@ -184,4 +186,3 @@ about what is 'lightweight'. ### Why isn't SQLite's amalgamated build on this list? Come on. - From 2c047c7a2713d45f119f4724844ef25108aca067 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 5 May 2016 14:53:42 -0700 Subject: [PATCH 342/522] Update other_libs.md --- docs/other_libs.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index ab64b7e..2d74fc1 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -19,7 +19,12 @@ Exceptions will be allowed for good reasons. See discussion after the list. -## Library listing +### JSON Parsing + +There are a lot of JSON parsers listed here. For some analysis and performance +results, check out https://github.com/miloyip/nativejson-benchmark + +### Library listing **Public domain single-file libraries usable from C and C++ are in bold.** Other libraries are either non-public domain, or two files, or not usable from both C and C++, or From 0a5cb5770605a9d46503ac723ed3dff600a56638 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Fri, 6 May 2016 01:07:45 +0200 Subject: [PATCH 343/522] other_libs.md: Add DG_dynarr.h --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2d74fc1..376e7e4 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -53,6 +53,7 @@ data structures|[klib](http://attractivechaos.github.io/klib/) data structures | [uthash](https://github.com/troydhanson/uthash) | BSD |C/C++| 2 | several 1-header, 1-license-file libs: generic hash, list, etc data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | C | 2 | memory-efficient array of elements with non-pow2 bitcount data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file binary tress (also regex, etc) +data structures |**[DG_dynarr.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| typesafe dynamic arrays (like std::vector) for plain C files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module files & filenames | [noc_file_dialog.h](https://github.com/guillaumechereau/noc) | MIT |C/C++| 1 | file open/save dialogs (Linux/OSX/Windows) From be5bf3213023b488fc8be62b18062bc868b57e4b Mon Sep 17 00:00:00 2001 From: jobtalle Date: Sat, 7 May 2016 11:24:32 +0200 Subject: [PATCH 344/522] Added ccVector reference --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2d74fc1..0fbd77d 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -94,6 +94,7 @@ images | [jpeg-compressor](https://github.com/richgel999/jpeg-compre images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math +math |**[ccVector.h](https://github.com/jobtalle/ccVector) | BSD |C/C++|**1**| Vector, quaternion and matrix math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math From d38d37c4ef8f41656d44d535b2066b0da0cb6faa Mon Sep 17 00:00:00 2001 From: jobtalle Date: Sat, 7 May 2016 11:25:54 +0200 Subject: [PATCH 345/522] Made link bold --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0fbd77d..e861f55 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -94,7 +94,7 @@ images | [jpeg-compressor](https://github.com/richgel999/jpeg-compre images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math -math |**[ccVector.h](https://github.com/jobtalle/ccVector) | BSD |C/C++|**1**| Vector, quaternion and matrix math +math |**[ccVector.h](https://github.com/jobtalle/ccVector)** | BSD |C/C++|**1**| Vector, quaternion and matrix math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math From 67e149fe18ce9b6b5c1397c9751e6734913ebf61 Mon Sep 17 00:00:00 2001 From: Fabio Pellacini Date: Sun, 8 May 2016 19:07:29 +0200 Subject: [PATCH 346/522] Update other_libs.md --- docs/other_libs.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2d74fc1..c1a3955 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -73,9 +73,10 @@ geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | C++ | 2 | line & polygon clipping & offsetting geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | C++ | 2 | polygon triangulation, partitioning geometry math | [Voxelizer](https://github.com/karimnaaji/voxelizer) | MIT |C/C++|**1**| convert triangle mesh to voxel triangle mesh -geometry math | [yocto_bvh.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| ray-casting of bounding-volume hierarchy +geometry math | [yocto_bvh.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| ray-casting and closest-element queries of bounding-volume hierarchy geometry math | [yocto_shape.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| shape generation, tesselation, normals, etc. -geometry math | [yocto_trace.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| physically-based unidirectional path tracer w/ MIS for direct lights +graphics (3d) | [yocto_trace.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| physically-based unidirectional path tracer w/ MIS for direct lights +graphics (3d) | [yocto_symrigid.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| rigid body simulator (sequential impulse/PGS) with support for concave objects graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows and OSX graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator From c9ead07188b342350530e92e14542222c3ad9abe Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 14 May 2016 21:59:06 -0700 Subject: [PATCH 347/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 2d74fc1..0585ae0 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -81,6 +81,7 @@ graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib |C/C++| 2 | compute tangent space for normal mapping graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering +graphics (3-D) |**[lightmapper](https://github.com/ands/lightmapper#lightmapper)** | **public domain** |C/C++|**1**| use your OpenGL renderer to offline bake lightmaps hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input images | [jo_gif.cpp](http://www.jonolick.com/home/gif-writer) | **public domain** | C++ |**1**| animated GIF writer (CPP file can also be used as H file) images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) From 365441bc7dc5b7bab64fc0221f8b1466766a0a3d Mon Sep 17 00:00:00 2001 From: Lewis Van Winkle Date: Wed, 18 May 2016 11:54:11 -0500 Subject: [PATCH 348/522] Added Genann (neural networks) --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0585ae0..2f91ecb 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -41,6 +41,7 @@ as C/C++, as this is not an obstacle to most users.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* +AI | [Genann](https://github.com/codeplea/genann) | zlib |C/C++| 2 | general-purpose neural networks argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | command-line argument parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder From cc1f71c0d16a2a436aef158645cb0da2de69bb88 Mon Sep 17 00:00:00 2001 From: Job Talle Date: Thu, 19 May 2016 13:50:31 +0200 Subject: [PATCH 349/522] Changed license to public domain --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index e861f55..c6bf3f2 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -94,7 +94,7 @@ images | [jpeg-compressor](https://github.com/richgel999/jpeg-compre images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math -math |**[ccVector.h](https://github.com/jobtalle/ccVector)** | BSD |C/C++|**1**| Vector, quaternion and matrix math +math |**[ccVector.h](https://github.com/jobtalle/ccVector)** | **public domain** |C/C++|**1**| Vector, quaternion and matrix math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math From a2bf7592b6e7a70ef5b0ff8896894d232ebb67f5 Mon Sep 17 00:00:00 2001 From: Viktor Kirilov Date: Sun, 22 May 2016 16:18:07 +0300 Subject: [PATCH 350/522] added doctest to the list with testing frameworks --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0585ae0..ffe6a96 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -127,6 +127,7 @@ strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings tests | [utest](https://github.com/evolutional/utest) | MIT |C/C++|**1**| unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | C++ |**1**| unit testing +tests | [doctest](https://github.com/onqtam/doctest) | MIT | C++ |**1**| the lightest feature rich C++ single header testing framework tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD |C/C++|**1**| unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing From 94dd6fe796464890e53d0f2db0b5aab04ed7091e Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Thu, 26 May 2016 22:48:01 +0100 Subject: [PATCH 351/522] README.md: add direct links to files --- README.md | 38 +++++++++++++++++++------------------- tools/make_readme.c | 7 +++++-- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index c40af5d..99c0137 100644 --- a/README.md +++ b/README.md @@ -7,25 +7,25 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**stb_vorbis.c** | 1.09 | audio | 5397 | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.12 | graphics | 6755 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.11 | graphics | 3267 | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP -**stb_image_resize.h** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality -**stb_rect_pack.h** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality -**stretchy_buffer.h** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**stb_textedit.h** | 1.8 | user interface | 1304 | guts of a text editor for games etc implementing them from scratch -**stb_voxel_render.h** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features -**stb_dxt.h** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor -**stb_perlin.h** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) -**stb_easy_font.h** | 0.7 | 3D graphics | 258 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc -**stb_tilemap_editor.h** | 0.37 | game dev | 4131 | embeddable tilemap editor -**stb_herringbone_wa...** | 0.6 | game dev | 1220 | herringbone Wang tile map generator -**stb_c_lexer.h** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages -**stb_divide.h** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**stb_connected_comp...** | 0.94 | misc | 1000 | incrementally compute reachability on grids -**stb.h** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff -**stb_leakcheck.h** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking +**[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5397 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_image.h](stb_image.h)** | 2.12 | graphics | 6755 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.11 | graphics | 3267 | parse, decode, and rasterize characters from truetype fonts +**[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP +**[stb_image_resize.h](stb_image_resize.h)** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality +**[stb_rect_pack.h](stb_rect_pack.h)** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality +**[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ +**[stb_textedit.h](stb_textedit.h)** | 1.8 | user interface | 1304 | guts of a text editor for games etc implementing them from scratch +**[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features +**[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor +**[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) +**[stb_easy_font.h](stb_easy_font.h)** | 0.7 | 3D graphics | 258 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc +**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.37 | game dev | 4131 | embeddable tilemap editor +**[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.6 | game dev | 1220 | herringbone Wang tile map generator +**[stb_c_lexer.h](stb_c_lexer.h)** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages +**[stb_divide.h](stb_divide.h)** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" +**[stb_connected_comp...](stb_connected_components.h)** | 0.94 | misc | 1000 | incrementally compute reachability on grids +**[stb.h](stb.h)** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 Total lines of C code: 47814 diff --git a/tools/make_readme.c b/tools/make_readme.c index 224f289..b28c4ff 100644 --- a/tools/make_readme.c +++ b/tools/make_readme.c @@ -30,15 +30,18 @@ int main(int argc, char **argv) if (*s1 == 'v') ++s1; s3 = tokens[0]; stb_trimwhite(s3); + fprintf(f, "**["); if (strlen(s3) < 21) { - fprintf(f, "**%s** | %s", tokens[0], s1); + fprintf(f, "%s", tokens[0]); } else { char buffer[256]; strncpy(buffer, s3, 18); buffer[18] = 0; strcat(buffer, "..."); - fprintf(f, "**%s** | %s", buffer, s1); + 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, " ", " "); // stb_dupreplace -- search & replace string and malloc result fprintf(f, " | %s", s2); From e1970fe45621022ac1267392c5ec5d6e6c3fff42 Mon Sep 17 00:00:00 2001 From: Danyil Bohdan Date: Sat, 4 Jun 2016 11:44:17 +0300 Subject: [PATCH 352/522] other_libs.md: Update link for LIL --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0585ae0..24183aa 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -117,7 +117,7 @@ parsing | [parson](https://github.com/kgabis/parson) parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 |C/C++| 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | C++ | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally -scripting | [LIL](http://runtimelegend.com/rep/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language +scripting | [LIL](http://runtimeterror.com/tech/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++|**1**| interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings From 734576e6be5ace1eb1064a95d3d25fb783ed237e Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 15 Jun 2016 10:36:39 +0200 Subject: [PATCH 353/522] image-write: fix monochrome bitmap writing from 8-bit-buffers Now writing out monochrome bitmaps from 8-bit arrays works as it does when using PNG. Bitmaps need 3 bytes per pixel. --- stb_image_write.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 4319c0d..c29cba9 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -293,9 +293,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in s->func(s->context, &d[comp - 1], 1); switch (comp) { - case 1: - s->func(s->context,d,1); - break; + case 1: /* fall-through wanted */ case 2: if (expand_mono) stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp From 21ea5487ffef64de297672b9e6589507ba226d7a Mon Sep 17 00:00:00 2001 From: Aras Pranckevicius Date: Thu, 30 Jun 2016 21:46:17 +0300 Subject: [PATCH 354/522] Fix crash when resizing large images (signed integer overflow, e.g. at image size of 24000x24000) --- stb_image_resize.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 4cabe54..e9a8ab0 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1239,11 +1239,11 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int type = stbir_info->type; int colorspace = stbir_info->colorspace; int input_w = stbir_info->input_w; - int input_stride_bytes = stbir_info->input_stride_bytes; + size_t input_stride_bytes = stbir_info->input_stride_bytes; float* decode_buffer = stbir__get_decode_buffer(stbir_info); stbir_edge edge_horizontal = stbir_info->edge_horizontal; stbir_edge edge_vertical = stbir_info->edge_vertical; - int in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; int decode = STBIR__DECODE(type, colorspace); From e75ca4234e22aa8eb6d0c3dc767f9c521bda193e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 16 Jul 2016 23:14:12 -0700 Subject: [PATCH 355/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 0585ae0..8604bae 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -61,6 +61,7 @@ files & filenames | [TinyDir](https://github.com/cxong/tinydir) geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | C++ |**1**| wavefront OBJ file loader +geometry file | [tinyobjloader_c](https://github.com/syoyo/tinyobjloader_c) | MIT | C |**1**| wavefront OBJ file loader geometry file | [yocto_obj.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| wavefront OBJ file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |C/C++|**1**| find voronoi regions on lattice w/ integer inputs geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |C/C++|**1**| sobol & stratified sampling sequences From 8eebc0915072ed988754d15d5e0b14ca6d6206b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bryon=20Gloden=2C=20CISSP=C2=AE?= Date: Thu, 4 Aug 2016 16:39:39 -0400 Subject: [PATCH 356/522] Update stb_c_lexer.h [stb_c_lexer.h:801]: (error) Memory leak: text [stb_c_lexer.h:801]: (error) Resource leak: f Found by https://github.com/bryongloden/cppcheck --- stb_c_lexer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index e91c6c3..efb8f94 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -798,6 +798,8 @@ int main(int argc, char **argv) stb_lexer lex; if (len < 0) { fprintf(stderr, "Error opening file\n"); + free(text); + fclose(f); return 1; } fclose(f); From 33b92cab0f9e96be74a552eda9e0b9c5dacdf1aa Mon Sep 17 00:00:00 2001 From: Terry Nguyen Date: Thu, 11 Aug 2016 12:40:49 -0700 Subject: [PATCH 357/522] Fix link to tinyobjloader-c The repository has been been relocated by syoyo from tinyobjloader_c to tinyobjloader-c (note the dash) --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8604bae..97db8ae 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -61,7 +61,7 @@ files & filenames | [TinyDir](https://github.com/cxong/tinydir) geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | C++ |**1**| wavefront OBJ file loader -geometry file | [tinyobjloader_c](https://github.com/syoyo/tinyobjloader_c) | MIT | C |**1**| wavefront OBJ file loader +geometry file | [tinyobjloader-c](https://github.com/syoyo/tinyobjloader-c) | MIT | C |**1**| wavefront OBJ file loader geometry file | [yocto_obj.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| wavefront OBJ file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |C/C++|**1**| find voronoi regions on lattice w/ integer inputs geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |C/C++|**1**| sobol & stratified sampling sequences From 00c6078f9d78ea7fdd87f8a3c972f9aca24b2106 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 20 Aug 2016 21:35:01 -0700 Subject: [PATCH 358/522] Handmade Math --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index 8604bae..e56cc72 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -96,6 +96,7 @@ images | [jpeg-compressor](https://github.com/richgel999/jpeg-compre images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math +math |**[Handmade Math](https://github.com/StrangeZak/Handmade-Math)** | **public domain** |C/C++|**1**| SIMD vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math From f9a04924af87a5566f7979c81b8c404b99d249ef Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 20 Aug 2016 21:36:01 -0700 Subject: [PATCH 359/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index e56cc72..1f7e7a6 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -96,7 +96,7 @@ images | [jpeg-compressor](https://github.com/richgel999/jpeg-compre images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math -math |**[Handmade Math](https://github.com/StrangeZak/Handmade-Math)** | **public domain** |C/C++|**1**| SIMD vector math +math |**[Handmade Math](https://github.com/StrangeZak/Handmade-Math)** | **public domain** |C/C++|**1**| vector math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math From ec6e5e40543c0c7d2dd6ddff6dc101011af10a67 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 09:48:58 -0700 Subject: [PATCH 360/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 1f7e7a6..39a4b5c 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -60,7 +60,7 @@ files & filenames | [dirent](https://github.com/tronkko/dirent) files & filenames | [TinyDir](https://github.com/cxong/tinydir) | BSD | C |**1**| cross-platform directory reader geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader -geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | BSD | C++ |**1**| wavefront OBJ file loader +geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | MIT | C++ |**1**| wavefront OBJ file loader geometry file | [tinyobjloader_c](https://github.com/syoyo/tinyobjloader_c) | MIT | C |**1**| wavefront OBJ file loader geometry file | [yocto_obj.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| wavefront OBJ file loader geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |C/C++|**1**| find voronoi regions on lattice w/ integer inputs From 4806aca183000a472e621388f15cc907f4caeac3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 12:02:26 -0700 Subject: [PATCH 361/522] windows fwrite doesn't handle arbitrarily large writes (!); add a bunch of stuff used by my backup program 'smir'; --- stb.h | 140 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 25 deletions(-) diff --git a/stb.h b/stb.h index b985b13..18bc37e 100644 --- a/stb.h +++ b/stb.h @@ -5189,7 +5189,18 @@ int stb_filewrite(char *filename, void *data, size_t length) { FILE *f = stb_fopen(filename, "wb"); if (f) { - fwrite(data, 1, length, f); + unsigned char *data_ptr = (unsigned char *) data; + size_t remaining = length; + while (remaining > 0) { + size_t len2 = remaining > 65536 ? 65536 : remaining; + size_t len3 = fwrite(data_ptr, 1, len2, f); + if (len2 != len3) { + fprintf(stderr, "Failed while writing %s\n", filename); + break; + } + remaining -= len2; + data_ptr += len2; + } stb_fclose(f, stb_keep_if_different); } return f != NULL; @@ -5789,6 +5800,19 @@ char *stb_strip_final_slash(char *t) } return t; } + +char *stb_strip_final_slash_regardless(char *t) +{ + if (t[0]) { + char *z = t + strlen(t) - 1; + // *z is the last character + if (*z == '\\' || *z == '/') + *z = 0; + if (*z == '\\') + *z = '/'; // canonicalize to make sure it matches db + } + return t; +} #endif ////////////////////////////////////////////////////////////////////////////// @@ -6746,14 +6770,16 @@ typedef struct char * path; // full path from passed-in root time_t last_modified; int num_files; + int flag; } stb_dirtree_dir; typedef struct { char *name; // name relative to path int dir; // index into dirs[] array - unsigned long size; // size, max 4GB + stb_int64 size; // size, max 4GB time_t last_modified; + int flag; } stb_dirtree_file; typedef struct @@ -6781,6 +6807,14 @@ extern stb_dirtree *stb_dirtree_get_with_file ( char *dir, char *cache_file); // do a call to stb_dirtree_get() with the same cache file at about the same // time, but I _think_ it might just work. +// i needed to build an identical data structure representing the state of +// a mirrored copy WITHOUT bothering to rescan it (i.e. we're mirroring to +// it WITHOUT scanning it, e.g. it's over the net), so this requires access +// to all of the innards. +extern void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last); +extern void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last); +extern void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir); +extern void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir); #ifdef STB_DEFINE static void stb__dirtree_add_dir(char *path, time_t last, stb_dirtree *active) @@ -6792,7 +6826,7 @@ static void stb__dirtree_add_dir(char *path, time_t last, stb_dirtree *active) stb_arr_push(active->dirs, d); } -static void stb__dirtree_add_file(char *name, int dir, unsigned long size, time_t last, stb_dirtree *active) +static void stb__dirtree_add_file(char *name, int dir, stb_int64 size, time_t last, stb_dirtree *active) { stb_dirtree_file f; f.dir = dir; @@ -6803,23 +6837,25 @@ static void stb__dirtree_add_file(char *name, int dir, unsigned long size, time_ stb_arr_push(active->files, f); } -static char stb__signature[12] = { 's', 'T', 'b', 'D', 'i', 'R', 't', 'R', 'e', 'E', '0', '1' }; +// version 02 supports > 4GB files +static char stb__signature[12] = { 's', 'T', 'b', 'D', 'i', 'R', 't', 'R', 'e', 'E', '0', '2' }; static void stb__dirtree_save_db(char *filename, stb_dirtree *data, char *root) { int i, num_dirs_final=0, num_files_final; + char *info = root ? root : ""; int *remap; FILE *f = fopen(filename, "wb"); if (!f) return; fwrite(stb__signature, sizeof(stb__signature), 1, f); - fwrite(root, strlen(root)+1, 1, f); + fwrite(info, strlen(info)+1, 1, f); // need to be slightly tricky and not write out NULLed directories, nor the root // build remapping table of all dirs we'll be writing out remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(data->dirs)); for (i=0; i < stb_arr_len(data->dirs); ++i) { - if (data->dirs[i].path == NULL || 0==stb_stricmp(data->dirs[i].path, root)) { + if (data->dirs[i].path == NULL || (root && 0==stb_stricmp(data->dirs[i].path, root))) { remap[i] = -1; } else { remap[i] = num_dirs_final++; @@ -6836,14 +6872,14 @@ static void stb__dirtree_save_db(char *filename, stb_dirtree *data, char *root) num_files_final = 0; for (i=0; i < stb_arr_len(data->files); ++i) - if (remap[data->files[i].dir] >= 0) + if (remap[data->files[i].dir] >= 0 && data->files[i].name) ++num_files_final; fwrite(&num_files_final, 4, 1, f); for (i=0; i < stb_arr_len(data->files); ++i) { - if (remap[data->files[i].dir] >= 0) { + if (remap[data->files[i].dir] >= 0 && data->files[i].name) { stb_fput_ranged(f, remap[data->files[i].dir], 0, num_dirs_final); - stb_fput_varlenu(f, data->files[i].size); + stb_fput_varlen64(f, data->files[i].size); fwrite(&data->files[i].last_modified, 4, 1, f); stb_fput_string(f, data->files[i].name); } @@ -6880,7 +6916,7 @@ static void stb__dirtree_load_db(char *filename, stb_dirtree *data, char *dir) stb_arr_setlen(data->files, n); for (i=0; i < stb_arr_len(data->files); ++i) { data->files[i].dir = stb_fget_ranged(f, 0, stb_arr_len(data->dirs)); - data->files[i].size = stb_fget_varlenu(f); + data->files[i].size = stb_fget_varlen64(f); fread(&data->files[i].last_modified, 4, 1, f); data->files[i].name = stb_fget_string(f, data->string_pool); if (data->files[i].name == NULL) goto bail; @@ -6894,6 +6930,7 @@ static void stb__dirtree_load_db(char *filename, stb_dirtree *data, char *dir) fclose(f); } +static int stb__dircount, stb__dircount_mask, stb__showfile; static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *active) { // this is dumb depth first; theoretically it might be faster @@ -6902,52 +6939,66 @@ static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *acti int n; - struct _wfinddata_t c_file; - #ifdef STB_PTR64 - intptr_t hFile; - #else + struct _wfinddatai64_t c_file; long hFile; - #endif stb__wchar full_path[1024]; int has_slash; + if (stb__showfile) printf("<"); has_slash = (path[0] && path[strlen(path)-1] == '/'); if (has_slash) - swprintf((wchar_t *)full_path, L"%s*", stb__from_utf8(path)); + swprintf(full_path, L"%s*", stb__from_utf8(path)); else - swprintf((wchar_t *)full_path, L"%s/*", stb__from_utf8(path)); + swprintf(full_path, L"%s/*", stb__from_utf8(path)); // it's possible this directory is already present: that means it was in the // cache, but its parent wasn't... in that case, we're done with it + if (stb__showfile) printf("C[%d]", stb_arr_len(active->dirs)); for (n=0; n < stb_arr_len(active->dirs); ++n) - if (0 == stb_stricmp(active->dirs[n].path, path)) + if (0 == stb_stricmp(active->dirs[n].path, path)) { + if (stb__showfile) printf("D"); return; + } + if (stb__showfile) printf("E"); // otherwise, we need to add it stb__dirtree_add_dir(path, last_time, active); n = stb_arr_lastn(active->dirs); - if( (hFile = _wfindfirst((const wchar_t *)full_path, &c_file )) != -1L ) { + if (stb__showfile) printf("["); + if( (hFile = _wfindfirsti64( full_path, &c_file )) != -1L ) { do { + if (stb__showfile) printf(")"); if (c_file.attrib & _A_SUBDIR) { // ignore subdirectories starting with '.', e.g. "." and ".." if (c_file.name[0] != '.') { char *new_path = (char *) full_path; - char *temp = stb__to_utf8((stb__wchar *)c_file.name); + char *temp = stb__to_utf8(c_file.name); + if (has_slash) sprintf(new_path, "%s%s", path, temp); else sprintf(new_path, "%s/%s", path, temp); + + if (stb__dircount_mask) { + ++stb__dircount; + if (!(stb__dircount & stb__dircount_mask)) { + printf("%s\r", new_path); + } + } + stb__dirtree_scandir(new_path, c_file.time_write, active); } } else { - char *temp = stb__to_utf8((stb__wchar *)c_file.name); + char *temp = stb__to_utf8(c_file.name); stb__dirtree_add_file(temp, n, c_file.size, c_file.time_write, active); } - } while( _wfindnext( hFile, &c_file ) == 0 ); - + if (stb__showfile) printf("("); + } while( _wfindnexti64( hFile, &c_file ) == 0 ); + if (stb__showfile) printf("]"); _findclose( hFile ); } + if (stb__showfile) printf(">\n"); } // scan the database and see if it's all valid @@ -6963,13 +7014,21 @@ static int stb__dirtree_update_db(stb_dirtree *db, stb_dirtree *active) for (i=0; i < stb_arr_len(db->dirs); ++i) { struct _stat info; + if (stb__dircount_mask) { + ++stb__dircount; + if (!(stb__dircount & stb__dircount_mask)) { + printf("."); + } + } if (0 == _stat(db->dirs[i].path, &info)) { if (info.st_mode & _S_IFDIR) { // it's still a directory, as expected - if (info.st_mtime > db->dirs[i].last_modified) { + int n = abs(info.st_mtime - db->dirs[i].last_modified); + if (n > 1 && n != 3600) { // the 3600 is a hack because sometimes this jumps for no apparent reason, even when no time zone or DST issues are at play // it's changed! force a rescan // we don't want to scan it until we've stat()d its // subdirs, though, so we queue it + if (stb__showfile) printf("Changed: %s - %08x:%08x\n", db->dirs[i].path, db->dirs[i].last_modified, info.st_mtime); stb_arr_push(rescan, i); // update the last_mod time db->dirs[i].last_modified = info.st_mtime; @@ -7047,6 +7106,8 @@ stb_dirtree *stb_dirtree_get_with_file(char *dir, char *cache_file) if (cache_file != NULL) stb__dirtree_load_db(cache_file, &db, stripped_dir); + else if (stb__showfile) + printf("No cache file\n"); active.files = NULL; active.dirs = NULL; @@ -7061,6 +7122,9 @@ stb_dirtree *stb_dirtree_get_with_file(char *dir, char *cache_file) stb__dirtree_scandir(stripped_dir, 0, &active); // no last_modified time available for root + if (stb__dircount_mask) + printf(" \r"); + // done with the DB; write it back out if any changes, i.e. either // 1. any inconsistency found between cached information and actual disk // or 2. if scanning the root found any new directories--which we detect because @@ -7089,7 +7153,7 @@ stb_dirtree *stb_dirtree_get_dir(char *dir, char *cache_dir) stb_sha1(sha, (unsigned char *) dir_lower, strlen(dir_lower)); strcpy(cache_file, cache_dir); s = cache_file + strlen(cache_file); - if (s[-1] != '/' && s[-1] != '\\') *s++ = '/'; + if (s[-1] != '//' && s[-1] != '\\') *s++ = '/'; strcpy(s, "dirtree_"); s += strlen(s); for (i=0; i < 8; ++i) { @@ -7123,6 +7187,32 @@ void stb_dirtree_free(stb_dirtree *d) stb__dirtree_free_raw(d); free(d); } + +void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last) +{ + stb__dirtree_add_dir(path, last, active); +} + +void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last) +{ + stb__dirtree_add_file(name, dir, size, last, active); +} + +void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir) +{ + char *s = stb_strip_final_slash(strdup(dir)); + target->dirs = 0; + target->files = 0; + target->string_pool = 0; + stb__dirtree_load_db(filename, target, s); + free(s); +} + +void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir) +{ + stb__dirtree_save_db(filename, target, 0); // don't strip out any directories +} + #endif // STB_DEFINE #endif // _WIN32 From f4938bfa4d81abf59c89fb0d0c4c942df10754e3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 12:09:01 -0700 Subject: [PATCH 362/522] Whitelist the compilers that need malloc.h for alloca --- stb_vorbis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 19459eb..620440d 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -553,12 +553,12 @@ enum STBVorbisError #include #include #include -#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) +#ifdef _MSC_VER #include +#endif #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) #include #endif -#endif #else // STB_VORBIS_NO_CRT #define NULL 0 #define malloc(s) 0 From 14e6a98469d8f378e5f6a1d77d166244fe452d6c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 12:10:46 -0700 Subject: [PATCH 363/522] clarify alloca #include whitelists --- stb_vorbis.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 620440d..c4f24d5 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -549,21 +549,23 @@ enum STBVorbisError #endif #ifndef STB_VORBIS_NO_CRT -#include -#include -#include -#include -#ifdef _MSC_VER -#include -#endif -#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) -#include -#endif + #include + #include + #include + #include + + // find definition of alloca if it's not in stdlib.h: + #ifdef _MSC_VER + #include + #endif + #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) + #include + #endif #else // STB_VORBIS_NO_CRT -#define NULL 0 -#define malloc(s) 0 -#define free(s) ((void) 0) -#define realloc(s) 0 + #define NULL 0 + #define malloc(s) 0 + #define free(s) ((void) 0) + #define realloc(s) 0 #endif // STB_VORBIS_NO_CRT #include From bde8f7c102ffb7d1020302f585e775d8e1f7021a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 12:32:45 -0700 Subject: [PATCH 364/522] tweaks to stb_textedit custom-move-by-word patch --- stb_textedit.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 0262df1..3bae1b1 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -611,15 +611,16 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat } #ifdef STB_TEXTEDIT_IS_SPACE -static int is_word_boundary( STB_TEXTEDIT_STRING *_str, int _idx ) +static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx ) { - return _idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str,_idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str, _idx) ) ) : 1; + return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; } #ifndef STB_TEXTEDIT_MOVEWORDLEFT -static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, int c ) +static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c ) { - while( c >= 0 && !is_word_boundary( _str, c ) ) + --c; // always move at least one character + while( c >= 0 && !is_word_boundary( str, c ) ) --c; if( c < 0 ) @@ -631,10 +632,11 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, int c #endif #ifndef STB_TEXTEDIT_MOVEWORDRIGHT -static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, int c ) +static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c ) { const int len = STB_TEXTEDIT_STRINGLEN(_str); - while( c < len && !is_word_boundary( _str, c ) ) + ++c; // always move at least one character + while( c < len && !is_word_boundary( str, c ) ) ++c; if( c > len ) @@ -771,7 +773,7 @@ retry: if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); else { - state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1); + state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); stb_textedit_clamp( str, state ); } break; @@ -780,7 +782,7 @@ retry: if( !STB_TEXT_HAS_SELECTION( state ) ) stb_textedit_prep_selection_at_cursor(state); - state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1); + state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); state->select_end = state->cursor; stb_textedit_clamp( str, state ); @@ -792,7 +794,7 @@ retry: if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); else { - state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1); + state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); stb_textedit_clamp( str, state ); } break; @@ -801,7 +803,7 @@ retry: if( !STB_TEXT_HAS_SELECTION( state ) ) stb_textedit_prep_selection_at_cursor(state); - state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1); + state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); state->select_end = state->cursor; stb_textedit_clamp( str, state ); From 4e758682b006b9d527e70532d3e71ae77acbbd44 Mon Sep 17 00:00:00 2001 From: cosmy1 Date: Tue, 3 May 2016 23:37:49 +0200 Subject: [PATCH 365/522] Minor fixes. --- stb_rect_pack.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index bd1cfc6..94d8a9e 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -148,7 +148,7 @@ enum { STBRP_HEURISTIC_Skyline_default=0, STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, - STBRP_HEURISTIC_Skyline_BF_sortHeight, + STBRP_HEURISTIC_Skyline_BF_sortHeight }; @@ -198,9 +198,15 @@ struct stbrp_context #define STBRP_ASSERT assert #endif +#ifdef _MSC_VER +#define STBRP__NOTUSED(v) (void)(v) +#else +#define STBRP__NOTUSED(v) (void)sizeof(v) +#endif + enum { - STBRP__INIT_skyline = 1, + STBRP__INIT_skyline = 1 }; STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) @@ -273,6 +279,9 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0 stbrp_node *node = first; int x1 = x0 + width; int min_y, visited_width, waste_area; + + STBRP__NOTUSED(c); + STBRP_ASSERT(first->x <= x0); #if 0 From 19c9615e9048fa7f1b9e144ef847d12b093289f4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 12:36:26 -0700 Subject: [PATCH 366/522] rect_pack patch; fix typo in stb_textedit --- stb_rect_pack.h | 4 ++-- stb_textedit.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index 94d8a9e..58e98ea 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -279,9 +279,9 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0 stbrp_node *node = first; int x1 = x0 + width; int min_y, visited_width, waste_area; - + STBRP__NOTUSED(c); - + STBRP_ASSERT(first->x <= x0); #if 0 diff --git a/stb_textedit.h b/stb_textedit.h index 3bae1b1..520cb03 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -634,7 +634,7 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c ) #ifndef STB_TEXTEDIT_MOVEWORDRIGHT static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c ) { - const int len = STB_TEXTEDIT_STRINGLEN(_str); + const int len = STB_TEXTEDIT_STRINGLEN(str); ++c; // always move at least one character while( c < len && !is_word_boundary( str, c ) ) ++c; From 6f72440159851b6057f4fc0c2e7dbbf5beab7235 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 12:38:09 -0700 Subject: [PATCH 367/522] bump version numbers --- stb.h | 3 ++- stb_rect_pack.h | 3 ++- stb_textedit.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/stb.h b/stb.h index 18bc37e..6831476 100644 --- a/stb.h +++ b/stb.h @@ -1,4 +1,4 @@ -/* stb.h - v2.27 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h +/* stb.h - v2.28 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h no warranty is offered or implied; use this code at your own risk This is a single header file with a bunch of useful utilities @@ -25,6 +25,7 @@ Version History + 2.28 various new functionality 2.27 test _WIN32 not WIN32 in STB_THREADS 2.26 various warning & bugfixes 2.25 various warning & bugfixes diff --git a/stb_rect_pack.h b/stb_rect_pack.h index 58e98ea..421ba40 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.08 - public domain - rectangle packing +// stb_rect_pack.h - v0.09 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -32,6 +32,7 @@ // // Version history: // +// 0.09 (2016-08-27) fix compiler warnings // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort diff --git a/stb_textedit.h b/stb_textedit.h index 520cb03..64cf2ca 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// stb_textedit.h - v1.8 - public domain - Sean Barrett +// stb_textedit.h - v1.9 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -31,6 +31,7 @@ // // VERSION HISTORY // +// 1.9 (2016-08-27) customizable move-by-word // 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.7 (2015-09-13) change y range handling in case baseline is non-0 // 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove From 5e596c8c2d550c94a32b9cb2b51d92b0ba251af3 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 27 Aug 2016 12:52:28 -0700 Subject: [PATCH 368/522] other_libs: fix indentation --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index df257fa..4734747 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -79,7 +79,7 @@ geometry math | [Voxelizer](https://github.com/karimnaaji/voxelizer) geometry math | [yocto_bvh.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| ray-casting and closest-element queries of bounding-volume hierarchy geometry math | [yocto_shape.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| shape generation, tesselation, normals, etc. graphics (3d) | [yocto_trace.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| physically-based unidirectional path tracer w/ MIS for direct lights -graphics (3d) | [yocto_symrigid.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| rigid body simulator (sequential impulse/PGS) with support for concave objects +graphics (3d) | [yocto_symrigid.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| rigid body simulator (sequential impulse/PGS) with support for concave objects graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows and OSX graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator From 973ad3611c4ce63fad89082cd0192f1ad163e60a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 28 Aug 2016 10:42:22 -0700 Subject: [PATCH 369/522] other_libs updates --- docs/other_libs.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 03899db..c286495 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -43,8 +43,9 @@ category | library AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | command-line argument parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder -audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder -audio |**[sts_mixer](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| simple stereo audio mixer +audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder +audio |**[dr_wav](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| WAV audio loader +audio |**[sts_mixer](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| simple stereo audio mixer compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression compression | [fastlz](https://code.google.com/archive/p/fastlz/source/default/source) | MIT |C/C++| 2 | fast but larger LZ compression @@ -56,7 +57,7 @@ data structures | [PackedArray](https://github.com/gpakosz/PackedArray) data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file binary tress (also regex, etc) data structures |**[DG_dynarr.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| typesafe dynamic arrays (like std::vector) for plain C files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -files & filenames | [whereami](https://github.com/gpakosz/whereami) |**WTFPLv2** |C/C++| 2 | get path/filename of executable or module +files & filenames | [whereami](https://github.com/gpakosz/whereami) | **WTFPLv2** |C/C++| 2 | get path/filename of executable or module files & filenames | [noc_file_dialog.h](https://github.com/guillaumechereau/noc) | MIT |C/C++| 1 | file open/save dialogs (Linux/OSX/Windows) files & filenames | [dirent](https://github.com/tronkko/dirent) | MIT |C/C++|**1**| dirent for windows: retrieve file & dir info files & filenames | [TinyDir](https://github.com/cxong/tinydir) | BSD | C |**1**| cross-platform directory reader @@ -100,21 +101,24 @@ images | [easyexif](https://github.com/mayanklahiri/easyexif) images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math math |**[Handmade Math](https://github.com/StrangeZak/Handmade-Math)** | **public domain** |C/C++|**1**| vector math +math |**[gb_math](https://github.com/gingerBill/gb/blob/master/gb_math.h)** | **public domain** |C/C++|**1**| Vector, quaternion and matrix math w/o math.h math |**[ccVector.h](https://github.com/jobtalle/ccVector)** | **public domain** |C/C++|**1**| Vector, quaternion and matrix math math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math math | [PoissonGenerator.h](https://github.com/corporateshark/poisson-disk-generator) | MIT | C++ |**1**| Poisson disk points generator (disk or rect) math | [prns.h](http://marc-b-reynolds.github.io/shf/2016/04/19/prns.html) | **public domain** |C/C++|**1**| seekable pseudo-random number sequences +math |**[aomeba](https://github.com/starwing/amoeba) | MIT |C/C++|**1**| constraint solver (Cassowary) w/Lua binding multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network |**[sts_net](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| cross-platform socket wrapper (socket sets and packet API) network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** |C/C++| 2 | non-production-use http server -network | [happyhttp](http://scumways.com/happyhttp/happyhttp.html) | zlib | C++ | 2 | http client requests +network | [happyhttp](https://github.com/Zintinio/HappyHTTP) | zlib | C++ | 2 | http client requests network | [mongoose](https://github.com/cesanta/mongoose) |_GPLv2_ |C/C++| 2 | http server network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | C++ | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 +network | [znet](https://github.com/starwing/znet) | MIT |C/C++|**1**| cross-platform networking w/ lua binding parsing | [SLRE](https://github.com/cesanta/slre) |_GPLv2_ |C/C++|**1**| regular expression matcher parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| C-esque language lexer From fa775881d6f85fdd9d6705aaed615f5244f780c9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 28 Aug 2016 11:04:38 -0700 Subject: [PATCH 370/522] Update other_libs.md --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/other_libs.md b/docs/other_libs.md index c286495..afa00c4 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -92,6 +92,7 @@ images | [jo_gif.cpp](http://www.jonolick.com/home/gif-writer) images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder images | [miniexr](https://github.com/aras-p/miniexr) | **public domain** | C++ | 2 | OpenEXR writer, needs header file +images | [gif_load](https://github.com/hidefromkgb/gif_load) | ??? |C/C++|**1**| (animated) GIF reader images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |C/C++|**1**| EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer From e713a69f1ea6ee1e0d55725ed0731520045a5993 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 28 Aug 2016 14:10:03 -0700 Subject: [PATCH 371/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index afa00c4..7f3ef85 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -91,8 +91,8 @@ hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** images | [jo_gif.cpp](http://www.jonolick.com/home/gif-writer) | **public domain** | C++ |**1**| animated GIF writer (CPP file can also be used as H file) images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder +images |**[gif_load](https://github.com/hidefromkgb/gif_load)** | **public domain** |C/C++|**1**| (animated) GIF reader images | [miniexr](https://github.com/aras-p/miniexr) | **public domain** | C++ | 2 | OpenEXR writer, needs header file -images | [gif_load](https://github.com/hidefromkgb/gif_load) | ??? |C/C++|**1**| (animated) GIF reader images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |C/C++|**1**| EXR image read/write, uses miniz internally images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer From c6b6239357e72b91e83ab2f4d6e474e27dbf11c1 Mon Sep 17 00:00:00 2001 From: Alan Hickman Date: Sun, 14 Aug 2016 18:34:35 -0700 Subject: [PATCH 372/522] stb_c_lexer.h: Compile fixes when not using CRT --- stb_c_lexer.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index e91c6c3..b60a641 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -373,7 +373,7 @@ static double stb__clex_parse_float(char *p, char **q) double powten=1, addend = 0; ++p; while (*p >= '0' && *p <= '9') { - addend = addend + 10*(*p++ - '0'); + addend = addend*10 + (*p++ - '0'); powten *= 10; } value += addend / powten; @@ -649,7 +649,7 @@ int stb_c_lexer_get_token(stb_lexer *lexer) break; ++q; } - lexer->int_field = n; // int_field is macro that expands to real_number/int_number depending on type of n + lexer->int_number = n; #endif if (q == p+2) return stb__clex_token(lexer, CLEX_parse_error, p-2,p-1); @@ -692,14 +692,14 @@ int stb_c_lexer_get_token(stb_lexer *lexer) stb__clex_int n=0; while (q != lexer->eof) { if (*q >= '0' && *q <= '7') - n = n*8 + (q - '0'); + n = n*8 + (*q - '0'); else break; ++q; } if (q != lexer->eof && (*q == '8' || *q=='9')) - return stb__clex_token(tok, CLEX_parse_error, p, q); - lexer->int_field = n; + return stb__clex_token(lexer, CLEX_parse_error, p, q); + lexer->int_number = n; #endif return stb__clex_parse_suffixes(lexer, CLEX_intlit, p,q, STB_C_LEX_OCTAL_SUFFIXES); } @@ -714,12 +714,12 @@ int stb_c_lexer_get_token(stb_lexer *lexer) stb__clex_int n=0; while (q != lexer->eof) { if (*q >= '0' && *q <= '9') - n = n*10 + (q - '0'); + n = n*10 + (*q - '0'); else break; ++q; } - lexer->int_field = n; + lexer->int_number = n; #endif return stb__clex_parse_suffixes(lexer, CLEX_intlit, p,q, STB_C_LEX_OCTAL_SUFFIXES); } @@ -732,6 +732,7 @@ int stb_c_lexer_get_token(stb_lexer *lexer) #ifdef STB_C_LEXER_SELF_TEST #include +#include static void print_token(stb_lexer *lexer) { @@ -787,7 +788,7 @@ multiline comments */ void dummy(void) { - printf("test",1); // https://github.com/nothings/stb/issues/13 + printf("test %d",1); // https://github.com/nothings/stb/issues/13 } int main(int argc, char **argv) From 49d3871d867e463cc622b1a5b0fb28fbe3ba18ab Mon Sep 17 00:00:00 2001 From: Alan Hickman Date: Sun, 14 Aug 2016 18:35:17 -0700 Subject: [PATCH 373/522] stb_c_lexer.h: C99 hex float literals * Add support for C99 hex float literals * + is acceptable in a floating-point exponent * log(n) implementation of pow for stb__clex_parse_float * Add hex int and float test cases --- stb_c_lexer.h | 158 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 127 insertions(+), 31 deletions(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index b60a641..66e5543 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -45,7 +45,8 @@ #define STB_C_LEX_C_DECIMAL_INTS Y // "0|[1-9][0-9]*" CLEX_intlit #define STB_C_LEX_C_HEX_INTS Y // "0x[0-9a-fA-F]+" CLEX_intlit #define STB_C_LEX_C_OCTAL_INTS Y // "[0-7]+" CLEX_intlit -#define STB_C_LEX_C_DECIMAL_FLOATS Y // "[0-9]*(.[0-9]*([eE]-?[0-9]+)?) CLEX_floatlit +#define STB_C_LEX_C_DECIMAL_FLOATS Y // "[0-9]*(.[0-9]*([eE][-+]?[0-9]+)?) CLEX_floatlit +#define STB_C_LEX_C99_HEX_FLOATS N // "0x{hex}+(.{hex}*)?[pP][-+]?{hex}+ CLEX_floatlit #define STB_C_LEX_C_IDENTIFIERS Y // "[_a-zA-Z][_a-zA-Z0-9]*" CLEX_id #define STB_C_LEX_C_DQ_STRINGS Y // double-quote-delimited strings with escapes CLEX_dqstring #define STB_C_LEX_C_SQ_STRINGS N // single-quote-delimited strings with escapes CLEX_ssstring @@ -171,11 +172,6 @@ extern void stb_c_lexer_get_location(const stb_lexer *lexer, const char *where, #define Y(x) 1 #define N(x) 0 -#if STB_C_LEX_USE_STDLIB(x) -#define STB__CLEX_use_stdlib -#include -#endif - #if STB_C_LEX_INTEGERS_AS_DOUBLES(x) typedef double stb__clex_int; #define intfield real_number @@ -200,6 +196,10 @@ typedef long stb__clex_int; #define STB__clex_define_shifts #endif +#if STB_C_LEX_C99_HEX_FLOATS(x) +#define STB__clex_hex_floats +#endif + #if STB_C_LEX_C_HEX_INTS(x) #define STB__clex_hex_ints #endif @@ -220,6 +220,11 @@ typedef long stb__clex_int; #define STB__clex_discard_preprocessor #endif +#if STB_C_LEX_USE_STDLIB(x) && (!defined(STB__clex_hex_floats) || __STDC_VERSION__ >= 199901L) +#define STB__CLEX_use_stdlib +#include +#endif + // Now pick a definition of Y/N that's conducive to // defining the enum of token names. #if STB_C_LEX_DEFINE_ALL_TOKEN_NAMES(x) || defined(STB_C_LEXER_SELF_TEST) @@ -364,34 +369,95 @@ static int stb__clex_parse_suffixes(stb_lexer *lexer, long tokenid, char *start, } #ifndef STB__CLEX_use_stdlib +static double stb__clex_pow(double base, unsigned int exponent) +{ + double value=1; + for ( ; exponent; exponent >>= 1) { + if (exponent & 1) + value *= base; + base *= base; + } + return value; +} + static double stb__clex_parse_float(char *p, char **q) { + char *s = p; double value=0; - while (*p >= '0' && *p <= '9') - value = value*10 + (*p++ - '0'); - if (*p == '.') { - double powten=1, addend = 0; - ++p; - while (*p >= '0' && *p <= '9') { - addend = addend*10 + (*p++ - '0'); - powten *= 10; + int base=10; + int exponent=0; + +#ifdef STB__clex_hex_floats + if (*p == '0') { + if (p[1] == 'x' || p[1] == 'X') { + base=16; + p += 2; } - value += addend / powten; } - if (*p == 'e' || *p == 'E') { +#endif + + for (;;) { + if (*p >= '0' && *p <= '9') + value = value*base + (*p++ - '0'); +#ifdef STB__clex_hex_floats + else if (base == 16 && *p >= 'a' && *p <= 'f') + value = value*base + 10 + (*p++ - 'a'); + else if (base == 16 && *p >= 'A' && *p <= 'F') + value = value*base + 10 + (*p++ - 'A'); +#endif + else + break; + } + + if (*p == '.') { + double pow, addend = 0; + ++p; + for (pow=1; ; pow*=base) { + if (*p >= '0' && *p <= '9') + addend = addend*base + (*p++ - '0'); +#ifdef STB__clex_hex_floats + else if (base == 16 && *p >= 'a' && *p <= 'f') + addend = addend*base + 10 + (*p++ - 'a'); + else if (base == 16 && *p >= 'A' && *p <= 'F') + addend = addend*base + 10 + (*p++ - 'A'); +#endif + else + break; + } + value += addend / pow; + } +#ifdef STB__clex_hex_floats + if (base == 16) { + // exponent required for hex float literal + if (*p != 'p' && *p != 'P') { + *q = s; + return 0; + } + exponent = 1; + } else +#endif + exponent = (*p == 'e' || *p == 'E'); + + if (exponent) { int sign = p[1] == '-'; - int exponent=0; - double pow10=1; - p += 1+sign; + unsigned int exponent=0; + double power=1; + ++p; + if (*p == '-' || *p == '+') + ++p; while (*p >= '0' && *p <= '9') exponent = exponent*10 + (*p++ - '0'); - // can't use pow() from stdlib, so do it slow way - while (exponent-- > 0) - pow10 *= 10; - if (sign) - value /= pow10; + +#ifdef STB__clex_hex_floats + if (base == 16) + power = stb__clex_pow(2, exponent); else - value *= pow10; +#endif + power = stb__clex_pow(10, exponent); + if (sign) + value /= power; + else + value *= power; } *q = p; return value; @@ -630,15 +696,37 @@ int stb_c_lexer_get_token(stb_lexer *lexer) goto single_char; case '0': - #ifdef STB__clex_hex_ints + #if defined(STB__clex_hex_ints) || defined(STB__clex_hex_floats) if (p+1 != lexer->eof) { if (p[1] == 'x' || p[1] == 'X') { - char *q = p+2; + char *q; + + #ifdef STB__clex_hex_floats + for (q=p+2; + q != lexer->eof && ((*q >= '0' && *q <= '9') || (*q >= 'a' && *q <= 'f') || (*q >= 'A' && *q <= 'F')); + ++q); + if (q != lexer->eof) { + if (*q == '.' STB_C_LEX_FLOAT_NO_DECIMAL(|| *q == 'p' || *q == 'P')) { + #ifdef STB__CLEX_use_stdlib + lexer->real_number = strtod((char *) p, (char**) &q); + #else + lexer->real_number = stb__clex_parse_float(p, &q); + #endif + + if (p == q) + return stb__clex_token(lexer, CLEX_parse_error, p,q); + return stb__clex_parse_suffixes(lexer, CLEX_floatlit, p,q, STB_C_LEX_FLOAT_SUFFIXES); + + } + } + #endif // STB__CLEX_hex_floats + + #ifdef STB__clex_hex_ints #ifdef STB__CLEX_use_stdlib lexer->int_number = strtol((char *) p, (char **) &q, 16); #else stb__clex_int n=0; - while (q != lexer->eof) { + for (q=p+2; q != lexer->eof; ++q) { if (*q >= '0' && *q <= '9') n = n*16 + (*q - '0'); else if (*q >= 'a' && *q <= 'f') @@ -647,16 +735,16 @@ int stb_c_lexer_get_token(stb_lexer *lexer) n = n*16 + (*q - 'A') + 10; else break; - ++q; } lexer->int_number = n; #endif if (q == p+2) return stb__clex_token(lexer, CLEX_parse_error, p-2,p-1); return stb__clex_parse_suffixes(lexer, CLEX_intlit, p,q, STB_C_LEX_HEX_SUFFIXES); + #endif } } - #endif // STB__clex_hex_ints + #endif // defined(STB__clex_hex_ints) || defined(STB__clex_hex_floats) // can't test for octal because we might parse '0.0' as float or as '0' '.' '0', // so have to do float first @@ -788,6 +876,14 @@ multiline comments */ void dummy(void) { + double some_floats[] = { + 1.0501, -10.4e12, 5E+10, +#ifdef STB__clex_hex_floats + 0x1.0p+24, 0xff.FP-8, 0x1p-23, +#endif + 4. + }; + printf("test %d",1); // https://github.com/nothings/stb/issues/13 } @@ -803,7 +899,7 @@ int main(int argc, char **argv) } fclose(f); - stb_c_lexer_init(&lex, text, text+len, (char *) malloc(1<<16), 1<<16); + stb_c_lexer_init(&lex, text, text+len, (char *) malloc(0x10000), 0x10000); while (stb_c_lexer_get_token(&lex)) { if (lex.token == CLEX_parse_error) { printf("\n<<>>\n"); From 4f51089d1db168a5cc931a2f2e49d1bf8d8ba11b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 25 Sep 2016 15:09:45 -0700 Subject: [PATCH 374/522] Update other_libs.md --- docs/other_libs.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 7f3ef85..a2c6005 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -40,7 +40,7 @@ as C/C++, as this is not an obstacle to most users.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- -AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* +AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A\* argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | command-line argument parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder @@ -109,7 +109,7 @@ math | [TinyExpr](https://github.com/codeplea/tinyexpr) math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math math | [PoissonGenerator.h](https://github.com/corporateshark/poisson-disk-generator) | MIT | C++ |**1**| Poisson disk points generator (disk or rect) math | [prns.h](http://marc-b-reynolds.github.io/shf/2016/04/19/prns.html) | **public domain** |C/C++|**1**| seekable pseudo-random number sequences -math |**[aomeba](https://github.com/starwing/amoeba) | MIT |C/C++|**1**| constraint solver (Cassowary) w/Lua binding +math | [aomeba](https://github.com/starwing/amoeba) | MIT |C/C++|**1**| constraint solver (Cassowary) w/Lua binding multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper network |**[sts_net](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| cross-platform socket wrapper (socket sets and packet API) @@ -146,6 +146,7 @@ tests | [greatest](https://github.com/silentbicycle/greatest) tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++ | 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** |C/C++|**1**| minimal GUI toolkit +video |**[jo_mpeg](http://www.jonolick.com/home/mpeg-video-writer)** | **public domain** |C/C++|**1**| mpeg file writer _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf From f814cd757773d67da209b744e834f00292c04ec7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 25 Sep 2016 17:10:51 -0700 Subject: [PATCH 375/522] Update other_libs.md --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index a2c6005..24bde80 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -146,7 +146,7 @@ tests | [greatest](https://github.com/silentbicycle/greatest) tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++ | 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** |C/C++|**1**| minimal GUI toolkit -video |**[jo_mpeg](http://www.jonolick.com/home/mpeg-video-writer)** | **public domain** |C/C++|**1**| mpeg file writer +video | [jo_mpeg](http://www.jonolick.com/home/mpeg-video-writer) | **public domain** | C++ |**1**| mpeg file writer _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging _misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf From 4a60c547109bd40d1879e479adac3f24c2f77b6e Mon Sep 17 00:00:00 2001 From: Martin Gerhardy Date: Fri, 30 Sep 2016 10:13:05 +0200 Subject: [PATCH 376/522] Shouldn't this be 6? --- tests/caveview/cave_render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/caveview/cave_render.c b/tests/caveview/cave_render.c index 7ac96ec..3ed4628 100644 --- a/tests/caveview/cave_render.c +++ b/tests/caveview/cave_render.c @@ -699,7 +699,7 @@ static int test_plane(plane *p, float x0, float y0, float z0, float x1, float y1 static int is_box_in_frustum(float *bmin, float *bmax) { int i; - for (i=0; i < 5; ++i) + for (i=0; i < 6; ++i) if (!test_plane(&frustum[i], bmin[0], bmin[1], bmin[2], bmax[0], bmax[1], bmax[2])) return 0; return 1; From 0181b37188698d0921d6df2d3a4cce5228f2fb13 Mon Sep 17 00:00:00 2001 From: Dougall Johnson Date: Sat, 24 Sep 2016 20:38:13 +1000 Subject: [PATCH 377/522] CFF and Type 2 charstream parsing in stb_truetype This is a partial implementation of the CFF and Type 2 charstring specifications. It allows stb_truetype to read most OTF files. --- stb_truetype.h | 722 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 711 insertions(+), 11 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index d360d60..bf04933 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -458,6 +458,14 @@ int main(int arg, char **argv) extern "C" { #endif +// private structure +typedef struct +{ + stbtt_uint8 *data; + int cursor; + int size; +} stbtt__buf; + ////////////////////////////////////////////////////////////////////////////// // // TEXTURE BAKING API @@ -648,6 +656,13 @@ struct stbtt_fontinfo int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict }; STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); @@ -725,7 +740,8 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in enum { STBTT_vmove=1, STBTT_vline, - STBTT_vcurve + STBTT_vcurve, + STBTT_vcubic }; #endif @@ -734,7 +750,7 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file typedef struct { - stbtt_vertex_type x,y,cx,cy; + stbtt_vertex_type x,y,cx,cy,cx1,cy1; unsigned char type,padding; } stbtt_vertex; #endif @@ -956,6 +972,152 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define STBTT__NOTUSED(v) (void)sizeof(v) #endif +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file @@ -1030,6 +1192,19 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, return -1; } +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) { stbtt_uint8 *data = (stbtt_uint8 *) data2; @@ -1038,6 +1213,7 @@ STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, i info->data = data; info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); cmap = stbtt__find_table(data, fontstart, "cmap"); // required info->loca = stbtt__find_table(data, fontstart, "loca"); // required @@ -1046,8 +1222,61 @@ STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, i info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required - if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) + + if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx, pdict; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } t = stbtt__find_table(data, fontstart, "maxp"); if (t) @@ -1198,6 +1427,8 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) { int g1,g2; + STBTT_assert(!info->cff.size); + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format @@ -1212,15 +1443,21 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) return g1==g2 ? -1 : g1; // if length is 0, return -1 } +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; - if (x0) *x0 = ttSHORT(info->data + g + 2); - if (y0) *y0 = ttSHORT(info->data + g + 4); - if (x1) *x1 = ttSHORT(info->data + g + 6); - if (y1) *y1 = ttSHORT(info->data + g + 8); + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } return 1; } @@ -1232,7 +1469,10 @@ STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, i STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) { stbtt_int16 numberOfContours; - int g = stbtt__GetGlyfOffset(info, glyph_index); + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); if (g < 0) return 1; numberOfContours = ttSHORT(info->data + g); return numberOfContours == 0; @@ -1254,7 +1494,7 @@ static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_ return num_vertices; } -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { stbtt_int16 numberOfContours; stbtt_uint8 *endPtsOfContours; @@ -1480,6 +1720,416 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s return num_vertices; } +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__cstx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__cstx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__cstx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__cstx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__cstx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // fallthrough + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) { + *x0 = r ? c.min_x : 0; + *y0 = r ? c.min_y : 0; + *x1 = r ? c.max_x : 0; + *y1 = r ? c.max_y : 0; + } + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) { stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); @@ -2350,6 +3000,48 @@ static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x return 1; } +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2); + float shortlen = STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + // returns number of contours static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { @@ -2406,6 +3098,14 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, objspace_flatness_squared, 0); x = vertices[i].x, y = vertices[i].y; break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; } } (*contour_lengths)[n] = num_points - start; From cf51044bc6b24e7a86216f75b4918d83f097ea62 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 08:23:24 -0700 Subject: [PATCH 378/522] update stb_pg project --- tests/stb.dsp | 4 ++++ tests/stb.dsw | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/stb.dsp b/tests/stb.dsp index eff7541..7fbb0a8 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -150,6 +150,10 @@ SOURCE=..\stb_perlin.h # End Source File # Begin Source File +SOURCE=..\stb_pg.h +# End Source File +# Begin Source File + SOURCE=..\stb_rect_pack.h # End Source File # Begin Source File diff --git a/tests/stb.dsw b/tests/stb.dsw index f73f9b1..45a52b6 100644 --- a/tests/stb.dsw +++ b/tests/stb.dsw @@ -63,6 +63,18 @@ Package=<4> ############################################################################### +Project: "pg_test"=.\pg_test\pg_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Project: "resize"=.\resize.dsp - Package Owner=<4> Package=<5> From 7fa4f1204803641a3f46a1d2182c492ccf939f45 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 08:25:24 -0700 Subject: [PATCH 379/522] tweak doctest --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 9efa04a..4f556ab 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -134,7 +134,7 @@ strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings tests | [utest](https://github.com/evolutional/utest) | MIT |C/C++|**1**| unit testing tests | [catch](https://github.com/philsquared/Catch) | Boost | C++ |**1**| unit testing -tests | [doctest](https://github.com/onqtam/doctest) | MIT | C++ |**1**| the lightest feature rich C++ single header testing framework +tests | [doctest](https://github.com/onqtam/doctest) | MIT | C++ |**1**| unit testing tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD |C/C++|**1**| unit testing tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing From a117f374b2aabe6717b4a90e9f1c9173a7ffe6fb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 08:30:52 -0700 Subject: [PATCH 380/522] update readme with links --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 99c0137..8a1ea38 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,14 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5397 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5399 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_image.h](stb_image.h)** | 2.12 | graphics | 6755 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.11 | graphics | 3267 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality -**[stb_rect_pack.h](stb_rect_pack.h)** | 0.08 | graphics | 572 | simple 2D rectangle packer with decent quality +**[stb_rect_pack.h](stb_rect_pack.h)** | 0.09 | graphics | 582 | simple 2D rectangle packer with decent quality **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**[stb_textedit.h](stb_textedit.h)** | 1.8 | user interface | 1304 | guts of a text editor for games etc implementing them from scratch +**[stb_textedit.h](stb_textedit.h)** | 1.9 | user interface | 1315 | guts of a text editor for games etc implementing them from scratch **[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features **[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) @@ -24,11 +24,11 @@ library | lastest version | category | LoC | description **[stb_c_lexer.h](stb_c_lexer.h)** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" **[stb_connected_comp...](stb_connected_components.h)** | 0.94 | misc | 1000 | incrementally compute reachability on grids -**[stb.h](stb.h)** | 2.27 | misc | 14185 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**[stb.h](stb.h)** | 2.28 | misc | 14276 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 -Total lines of C code: 47814 +Total lines of C code: 47928 FAQ From 97305532a9f8d2d4281a37154f38244ca552524e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 08:37:42 -0700 Subject: [PATCH 381/522] tweak genann --- docs/other_libs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 1d16e43..578d212 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -41,7 +41,7 @@ as C/C++, as this is not an obstacle to most users.) category | library | license | API |files| description ----------------- | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A* -AI | [Genann](https://github.com/codeplea/genann) | zlib |C/C++| 2 | general-purpose neural networks +AI | [Genann](https://github.com/codeplea/genann) | zlib |C/C++| 2 | simple neural networks (ANN) argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | command-line argument parsing audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder From 33ac18a7fbaa3bc039b0ac38e5ec5a877bd4dd2f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 08:43:38 -0700 Subject: [PATCH 382/522] tinyfiledialogs --- docs/other_libs.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/other_libs.md b/docs/other_libs.md index 43e00a0..9f4e47f 100644 --- a/docs/other_libs.md +++ b/docs/other_libs.md @@ -59,7 +59,6 @@ data structures | [minilibs](https://github.com/ccxvii/minilibs) data structures |**[DG_dynarr.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| typesafe dynamic arrays (like std::vector) for plain C files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings files & filenames | [whereami](https://github.com/gpakosz/whereami) | **WTFPLv2** |C/C++| 2 | get path/filename of executable or module -files & filenames | [noc_file_dialog.h](https://github.com/guillaumechereau/noc) | MIT |C/C++| 1 | file open/save dialogs (Linux/OSX/Windows) files & filenames | [dirent](https://github.com/tronkko/dirent) | MIT |C/C++|**1**| dirent for windows: retrieve file & dir info files & filenames | [TinyDir](https://github.com/cxong/tinydir) | BSD | C |**1**| cross-platform directory reader geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader @@ -130,7 +129,7 @@ parsing | [parson](https://github.com/kgabis/parson) parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file regex (also binary tree, etc) profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 |C/C++| 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | C++ | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally -scripting | [LIL](http://runtimeterror.com/tech/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language +scripting | [LIL](http://runtimeterror.com/tech/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++|**1**| interpreter for a Tcl-like scripting language strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings @@ -145,9 +144,11 @@ tests | [SPUT](http://www.lingua-systems.com/unit-testing/) tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing tests | [greatest](https://github.com/silentbicycle/greatest) | iSC | C |**1**| unit testing -tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing +tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++ | 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** |C/C++|**1**| minimal GUI toolkit +user interface | [noc_file_dialog.h](https://github.com/guillaumechereau/noc) | MIT |C/C++| 1 | file open/save dialogs (Linux/OSX/Windows) +user interface | [tinyfiledialogs](https://sourceforge.net/projects/tinyfiledialogs/) | ZLIB |C/C++| 2 | modal dialogs inc. file open/save (Linux/OSX/Windows) video | [jo_mpeg](http://www.jonolick.com/home/mpeg-video-writer) | **public domain** | C++ |**1**| mpeg file writer _misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently _misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging From 5ecb2d86b89985072d6621c11919d87eaa79fc4d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 08:55:48 -0700 Subject: [PATCH 383/522] Delete other_libs.md --- docs/other_libs.md | 208 --------------------------------------------- 1 file changed, 208 deletions(-) delete mode 100644 docs/other_libs.md diff --git a/docs/other_libs.md b/docs/other_libs.md deleted file mode 100644 index 9f4e47f..0000000 --- a/docs/other_libs.md +++ /dev/null @@ -1,208 +0,0 @@ -# Other single-file public-domain/open source libraries with minimal dependencies - -In addition to all of [my libraries](https://github.com/nothings/stb), there are other, similar libraries. - -The following is a list of small, easy-to-integrate, portable libraries -which are usable from C and/or C++, and should be able to be compiled on both -32-bit and 64-bit platforms. - -### Rules - -- Libraries must be usable from C or C++, ideally both -- Libraries should be usable from more than one platform (ideally, all major desktops and/or all major mobile) -- Libraries should compile and work on both 32-bit and 64-bit platforms -- Libraries should use at most two files - -Exceptions will be allowed for good reasons. - -### New libraries and corrections - -See discussion after the list. - -### JSON Parsing - -There are a lot of JSON parsers listed here. For some analysis and performance -results, check out https://github.com/miloyip/nativejson-benchmark - -### Library listing - -**Public domain single-file libraries usable from C and C++ are in bold.** Other -libraries are either non-public domain, or two files, or not usable from both C and C++, or -all three. Libraries of more than two files are mostly forbidden. - -For the API column, "C" means C only, "C++" means C++ only, and "C/C++" means C/C++ usable -from either; some files may require *building* as C or C++ but still qualify as "C/C++" as -long as the header file uses `extern "C"` to make it work. (In some cases, a header-file-only -library may compile as both C or C++, but produce an implementation that can only be called from -one or the other, because of a lack of use of `extern "C"`; in this case the table still qualifies it -as C/C++, as this is not an obstacle to most users.) - - -category | library | license | API |files| description ------------------ | --------------------------------------------------------------------- |:--------------------:|:---:|:---:| ----------- -AI | [micropather](http://www.grinninglizard.com/MicroPather/) | zlib | C++ | 2 | pathfinding with A\* -AI | [Genann](https://github.com/codeplea/genann) | zlib |C/C++| 2 | simple neural networks (ANN) -argv | [parg](https://github.com/jibsen/parg) | **public domain** | C | 1 | command-line argument parsing -audio | [aw_ima.h](https://github.com/afterwise/aw-ima/blob/master/aw-ima.h) | MIT |C/C++|**1**| IMA-ADPCM audio decoder -audio |**[dr_flac](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| FLAC audio decoder -audio |**[dr_wav](https://github.com/mackron/dr_libs)** | **public domain** |C/C++|**1**| WAV audio loader -audio |**[sts_mixer](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| simple stereo audio mixer -compression |**[miniz.c](https://github.com/richgel999/miniz)** |**public domain**|C/C++|**1**| compression,decompression, zip file, png writing -compression | [lz4](https://github.com/Cyan4973/lz4) | BSD |C/C++| 2 | fast but larger LZ compression -compression | [fastlz](https://code.google.com/archive/p/fastlz/source/default/source) | MIT |C/C++| 2 | fast but larger LZ compression -compression | [pithy](https://github.com/johnezang/pithy) | BSD |C/C++| 2 | fast but larger LZ compression -crypto | [TweetNaCl](http://tweetnacl.cr.yp.to/software.html) | **public domain** | C | 2 | high-quality tiny cryptography library -data structures|[klib](http://attractivechaos.github.io/klib/) | MIT |C/C++| 2 | many 2-file libs: hash, sort, b-tree, etc -data structures | [uthash](https://github.com/troydhanson/uthash) | BSD |C/C++| 2 | several 1-header, 1-license-file libs: generic hash, list, etc -data structures | [PackedArray](https://github.com/gpakosz/PackedArray) | **WTFPLv2** | C | 2 | memory-efficient array of elements with non-pow2 bitcount -data structures | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file binary tress (also regex, etc) -data structures |**[DG_dynarr.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| typesafe dynamic arrays (like std::vector) for plain C -files & filenames |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -files & filenames | [whereami](https://github.com/gpakosz/whereami) | **WTFPLv2** |C/C++| 2 | get path/filename of executable or module -files & filenames | [dirent](https://github.com/tronkko/dirent) | MIT |C/C++|**1**| dirent for windows: retrieve file & dir info -files & filenames | [TinyDir](https://github.com/cxong/tinydir) | BSD | C |**1**| cross-platform directory reader -geometry file | [tk_objfile](https://github.com/joeld42/tk_objfile) | MIT |C/C++|**1**| OBJ file loader -geometry file | [tinyply](https://github.com/ddiakopoulos/tinyply) | **public domain** | C++ | 2 | PLY mesh file loader -geometry file | [tinyobjloader](https://github.com/syoyo/tinyobjloader) | MIT | C++ |**1**| wavefront OBJ file loader -geometry file | [tinyobjloader-c](https://github.com/syoyo/tinyobjloader-c) | MIT | C |**1**| wavefront OBJ file loader -geometry file | [yocto_obj.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| wavefront OBJ file loader -geometry math |**[nv_voronoi.h](http://www.icculus.org/~mordred/nvlib/)** | **public domain** |C/C++|**1**| find voronoi regions on lattice w/ integer inputs -geometry math |**[sobol.h](https://github.com/Marc-B-Reynolds/Stand-alone-junk/)** | **public domain** |C/C++|**1**| sobol & stratified sampling sequences -geometry math | [sdf.h](https://github.com/memononen/SDF) | MIT |C/C++|**1**| compute signed-distance field from antialiased image -geometry math | [nanoflann](https://github.com/jlblancoc/nanoflann) | BSD | C++ |**1**| build KD trees for point clouds -geometry math | [jc_voronoi](https://github.com/JCash/voronoi) | MIT |C/C++|**1**| find voronoi regions on float/double data -geometry math | [par_msquares](https://github.com/prideout/par) | MIT |C/C++|**1**| convert (binarized) image to triangles -geometry math | [par_shapes](http://github.prideout.net/shapes) | MIT |C/C++|**1**| generate various 3d geometric shapes -geometry math | [Tomas Akenine-Moller snippets](http://tinyurl.com/ht79ndj) | **public domain** |C/C++| 2 | various 3D intersection calculations, not lib-ified -geometry math | [Clipper](http://www.angusj.com/delphi/clipper.php) | Boost | C++ | 2 | line & polygon clipping & offsetting -geometry math | [PolyPartition](https://github.com/ivanfratric/polypartition) | MIT | C++ | 2 | polygon triangulation, partitioning -geometry math | [Voxelizer](https://github.com/karimnaaji/voxelizer) | MIT |C/C++|**1**| convert triangle mesh to voxel triangle mesh -geometry math | [yocto_bvh.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| ray-casting and closest-element queries of bounding-volume hierarchy -geometry math | [yocto_shape.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| shape generation, tesselation, normals, etc. -graphics (3d) | [yocto_trace.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| physically-based unidirectional path tracer w/ MIS for direct lights -graphics (3d) | [yocto_symrigid.h](https://github.com/xelatihy/yocto-gl) | MIT |C/C++|**1**| rigid body simulator (sequential impulse/PGS) with support for concave objects -graphics (2d) | [blendish](https://bitbucket.org/duangle/oui-blendish/src) | MIT |C/C++|**1**| blender-style widget rendering -graphics (2d) | [tigr](https://bitbucket.org/rmitton/tigr/src) | **public domain** |C/C++| 2 | quick-n-dirty window text/graphics for Windows and OSX -graphics (2d) | [noc_turtle](https://github.com/guillaumechereau/noc) | MIT |C/C++| 2 | procedural graphics generator -graphics (3-D) | [mikktspace](http://tinyurl.com/z6xtucm) | zlib |C/C++| 2 | compute tangent space for normal mapping -graphics (3-D) | [debug-draw](https://github.com/glampert/debug-draw) | **public domain** | C++ |**1**| API-agnostic immediate-mode debug rendering -graphics (3-D) |**[lightmapper](https://github.com/ands/lightmapper#lightmapper)** | **public domain** |C/C++|**1**| use your OpenGL renderer to offline bake lightmaps -hardware |**[EasyTab](https://github.com/ApoorvaJ/EasyTab)** | **public domain** |C/C++|**1**| multi-platform tablet input -images | [jo_gif.cpp](http://www.jonolick.com/home/gif-writer) | **public domain** | C++ |**1**| animated GIF writer (CPP file can also be used as H file) -images |**[gif.h](https://github.com/ginsweater/gif-h)** | **public domain** | C |**1**| animated GIF writer (can only include once) -images |**[tiny_jpeg.h](https://github.com/serge-rgb/TinyJPEG/)** | **public domain** |C/C++|**1**| JPEG encoder -images |**[gif_load](https://github.com/hidefromkgb/gif_load)** | **public domain** |C/C++|**1**| (animated) GIF reader -images | [miniexr](https://github.com/aras-p/miniexr) | **public domain** | C++ | 2 | OpenEXR writer, needs header file -images | [tinyexr](https://github.com/syoyo/tinyexr) | BSD |C/C++|**1**| EXR image read/write, uses miniz internally -images | [lodepng](http://lodev.org/lodepng/) | zlib |C/C++| 2 | PNG encoder/decoder -images | [nanoSVG](https://github.com/memononen/nanosvg) | zlib |C/C++|**1**| 1-file SVG parser; 1-file SVG rasterizer -images | [picopng.cpp](http://lodev.org/lodepng/picopng.cpp) | zlib | C++ | 2 | tiny PNG loader -images | [jpeg-compressor](https://github.com/richgel999/jpeg-compressor) | **public domain** | C++ | 2 | 2-file jpeg compress, 2-file jpeg decompress -images | [easyexif](https://github.com/mayanklahiri/easyexif) | MIT | C++ | 2 | EXIF metadata extractor for JPEG images -images |**[cro_mipmap.h](https://github.com/thebeast33/cro_lib)** | **public domain** |C/C++|**1**| average, min, max mipmap generators -math | [mm_vec.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| SIMD vector math -math |**[Handmade Math](https://github.com/StrangeZak/Handmade-Math)** | **public domain** |C/C++|**1**| vector math -math |**[gb_math](https://github.com/gingerBill/gb/blob/master/gb_math.h)** | **public domain** |C/C++|**1**| Vector, quaternion and matrix math w/o math.h -math |**[ccVector.h](https://github.com/jobtalle/ccVector)** | **public domain** |C/C++|**1**| Vector, quaternion and matrix math -math | [ShaderFastLibs](https://github.com/michaldrobot/ShaderFastLibs) | MIT | C++ |**1**| (also HLSL) approximate transcendental functions optimized for shaders (esp. GCN) -math | [TinyExpr](https://github.com/codeplea/tinyexpr) | zlib | C | 2 | evaluation of math expressions from strings -math | [linalg.h](https://github.com/sgorsten/linalg) | **unlicense** | C++ |**1**| vector/matrix/quaternion math -math | [PoissonGenerator.h](https://github.com/corporateshark/poisson-disk-generator) | MIT | C++ |**1**| Poisson disk points generator (disk or rect) -math | [prns.h](http://marc-b-reynolds.github.io/shf/2016/04/19/prns.html) | **public domain** |C/C++|**1**| seekable pseudo-random number sequences -math | [aomeba](https://github.com/starwing/amoeba) | MIT |C/C++|**1**| constraint solver (Cassowary) w/Lua binding -multithreading | [mm_sched.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| cross-platform multithreaded task scheduler -network |**[zed_net](https://github.com/ZedZull/zed_net)** | **public domain** |C/C++|**1**| cross-platform socket wrapper -network |**[sts_net](https://github.com/kieselsteini/sts)** | **public domain** |C/C++|**1**| cross-platform socket wrapper (socket sets and packet API) -network | [mm_web.h](https://github.com/vurtun/mmx) | BSD |C/C++|**1**| lightweight webserver, fork of webby -network | [par_easycurl.h](https://github.com/prideout/par) | MIT |C/C++|**1**| curl wrapper -network | [yocto](https://github.com/tom-seddon/yhs) | **public domain** |C/C++| 2 | non-production-use http server -network | [happyhttp](https://github.com/Zintinio/HappyHTTP) | zlib | C++ | 2 | http client requests -network | [mongoose](https://github.com/cesanta/mongoose) |_GPLv2_ |C/C++| 2 | http server -network | [LUrlParser](https://github.com/corporateshark/LUrlParser) | MIT | C++ | 2 | lightweight URL & URI parser RFC 1738, RFC 3986 -network | [znet](https://github.com/starwing/znet) | MIT |C/C++|**1**| cross-platform networking w/ lua binding -parsing | [SLRE](https://github.com/cesanta/slre) |_GPLv2_ |C/C++|**1**| regular expression matcher -parsing | [PicoJSON](https://github.com/kazuho/picojson) | BSD | C++ |**1**| JSON parse/serializer -parsing | [mm_lexer.h](https://github.com/vurtun/mmx) | zlib |C/C++|**1**| C-esque language lexer -parsing | [json.h](https://github.com/sheredom/json.h) | **public domain** |C/C++| 2 | JSON parser -parsing | [jzon.h](https://github.com/Zguy/Jzon) | MIT | C++ | 2 | JSON parser -parsing | [parson](https://github.com/kgabis/parson) | MIT |C/C++| 2 | JSON parser and serializer -parsing | [minilibs](https://github.com/ccxvii/minilibs) | **public domain** | C | 2 | two-file regex (also binary tree, etc) -profiling | [Remotery](https://github.com/Celtoys/Remotery) | Apache 2.0 |C/C++| 2 | CPU/GPU profiler Win/Mac/Linux, using web browser for viewer -profiling | [MicroProfile](https://bitbucket.org/jonasmeyer/microprofile) | **unlicense** | C++ | 2-4 | CPU (and GPU?) profiler, 1-3 header files, uses miniz internally -scripting | [LIL](http://runtimeterror.com/tech/lil/) | zlib |C/C++| 2 | interpreter for a Tcl-like scripting language -scripting | [lualite](https://github.com/janezz55/lualite/) | MIT | C++ |**1**| generate lua bindings in C++ -scripting | [Picol](https://chiselapp.com/user/dbohdan/repository/picol/) | BSD |C/C++|**1**| interpreter for a Tcl-like scripting language -strings |**[DG_misc.h](https://github.com/DanielGibson/Snippets/)** | **public domain** |C/C++|**1**| Daniel Gibson's stb.h-esque cross-platform helpers: path/file, strings -strings |**[utf8](https://github.com/sheredom/utf8.h)** | **public domain** |C/C++|**1**| utf8 string library -strings |**[strpool.h](https://github.com/mattiasgustavsson/libs)** | **public domain** |C/C++|**1**| string interning -strings | [dfa](http://bjoern.hoehrmann.de/utf-8/decoder/dfa/) | MIT |C/C++| 2 | fast utf8 decoder (need a header file) -strings |**[gb_string.h](https://github.com/gingerBill/gb)** | **public domain** |C/C++|**1**| dynamic strings -tests | [utest](https://github.com/evolutional/utest) | MIT |C/C++|**1**| unit testing -tests | [catch](https://github.com/philsquared/Catch) | Boost | C++ |**1**| unit testing -tests | [doctest](https://github.com/onqtam/doctest) | MIT | C++ |**1**| unit testing -tests | [SPUT](http://www.lingua-systems.com/unit-testing/) | BSD |C/C++|**1**| unit testing -tests | [pempek_assert.cpp](https://github.com/gpakosz/Assert) | **WTFPLv2** | C++ | 2 | flexible assertions -tests | [minctest](https://github.com/codeplea/minctest) | zlib | C |**1**| unit testing -tests | [greatest](https://github.com/silentbicycle/greatest) | iSC | C |**1**| unit testing -tests | [µnit](https://github.com/nemequ/munit) | MIT | C |**1**| unit testing -user interface | [dear imgui](https://github.com/ocornut/imgui) | MIT | C++ | 9 | an immediate-mode GUI formerly named "ImGui"; [3rd-party C wrapper](https://github.com/Extrawurst/cimgui) -user interface | [nuklear](https://github.com/vurtun/nuklear) | **public domain** |C/C++|**1**| minimal GUI toolkit -user interface | [noc_file_dialog.h](https://github.com/guillaumechereau/noc) | MIT |C/C++| 1 | file open/save dialogs (Linux/OSX/Windows) -user interface | [tinyfiledialogs](https://sourceforge.net/projects/tinyfiledialogs/) | ZLIB |C/C++| 2 | modal dialogs inc. file open/save (Linux/OSX/Windows) -video | [jo_mpeg](http://www.jonolick.com/home/mpeg-video-writer) | **public domain** | C++ |**1**| mpeg file writer -_misc_ | [MakeID.h](http://www.humus.name/3D/MakeID.h) | **public domain** | C++ |**1**| allocate/deallocate small integer IDs efficiently -_misc_ | [loguru](https://github.com/emilk/loguru) | **public domain** | C++ |**1**| flexible logging -_misc_ | [tinyformat](https://github.com/c42f/tinyformat) | Boost | C++ |**1**| typesafe printf -_misc_ | [dbgtools](https://github.com/wc-duck/dbgtools) | zlib |C/C++| 2 | cross-platform debug util libraries -_misc_ | [stmr](https://github.com/wooorm/stmr.c) | MIT | C | 2 | extract English word stems -_misc_ | [levenshtein](https://github.com/wooorm/levenshtein.c) | MIT | C | 2 | compute edit distance between two strings - -There are also these XML libraries, but if you're using XML, shame on you: - -- parsing: [tinyxml2](https://github.com/leethomason/tinyxml2): XML -- parsing: [pugixml](http://pugixml.org/): XML (MIT license) - -Also you might be interested in other related, but different lists: - -- [clib](https://github.com/clibs/clib/wiki/Packages): list of (mostly) small single C functions (licenses not listed) - -## New libraries and corrections - -Submissions of new libraries: I accept submissions (as issues or as pull requests). Please -note that every file that must be included in a user's project counts; a header and a source -file is 2 files, but a header file, source file, and LICENSE (if the license isn't in the -source file) is 3 files, and won't be accepted, because it's not 2 files. But actually -'LICENSE' is a problem for just dropping the library in a source tree anyway, since it's -not scoped to just the library, so library authors are encouraged to include the license in the -source file and not require a separate LICENSE. - -Corrections: if information for a library above is wrong, please send a correction as an -issue, pull request, or email. Note that if the list indicates a library works from both -C/C++, but it doesn't, this could be an error in the list or it could be a bug in the -library. If you find a library doesn't work in 32-bit or 64-bit, the library should be -removed from this list, unless it's a bug in the library. - -## *List FAQ* - -### Can I link directly to this list? - -Yes, you can just use this page. If you want a shorter, more readable link, you can use [this URL](https://github.com/nothings/stb#other_libs) to link to the FAQ question that links to this page. - -### Why isn't library XXX which is made of 3 or more files on this list? - -I draw the line arbitrarily at 2 files at most. (Note that some libraries that appear to -be two files require a separate LICENSE file, which made me leave them out). Some of these -libraries are still easy to drop into your project and build, so you might still be ok with them. -But since people come to stb for single-file public domain libraries, I feel that starts -to get too far from what we do here. - -### Why isn't library XXX which is at most two files and has minimal other dependencies on this list? - -Probably because I don't know about it, feel free to submit a pull request, issue, email, or tweet it at -me (it can be your own library or somebody else's). But I might not include it for various -other reasons, including subtleties of what is 'minimal other dependencies' and subtleties -about what is 'lightweight'. - -### Why isn't SQLite's amalgamated build on this list? - -Come on. From d9e0dfcd631a870abc7ef88ac4f592f2095c759a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 08:56:29 -0700 Subject: [PATCH 384/522] readme change link to other_libs --- README.md | 2 +- tools/README.footer.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a1ea38..8f77589 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ to do anything else, although I appreciate attribution. #### Are there other single-file public-domain/open source libraries with minimal dependencies out there? -[Yes.](https://github.com/nothings/stb/blob/master/docs/other_libs.md) +[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? diff --git a/tools/README.footer.md b/tools/README.footer.md index b9a52bf..e670b7f 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -10,7 +10,7 @@ to do anything else, although I appreciate attribution. #### Are there other single-file public-domain/open source libraries with minimal dependencies out there? -[Yes.](https://github.com/nothings/stb/blob/master/docs/other_libs.md) +[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? From 1a31473db826af86ddf8ce8a2cf224fe9a43d406 Mon Sep 17 00:00:00 2001 From: guitarfreak Date: Sat, 8 Oct 2016 01:59:11 +0200 Subject: [PATCH 385/522] Added block_selector --- stb_voxel_render.h | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index c49aa40..17c8fbc 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -2902,7 +2902,9 @@ static void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, in if (mm->input.selector) mesh = mm->input.selector[v_off]; - + else if (mm->input.block_selector) + mesh = mm->input.block_selector[mm->input.blocktype[v_off]]; + // check if we're going off the end if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) { mm->full = 1; @@ -3008,6 +3010,18 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po nrot[5] = (mm->input.selector[v_off - 1] >> 4) & 3; } #endif + } else if (mm->input.block_selector) { + #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING + if (mm->input.packed_compact == NULL) { + rot = (mm->input.block_selector[bt ] >> 4) & 3; + nrot[0] = (mm->input.block_selector[nbt[0]] >> 4) & 3; + nrot[1] = (mm->input.block_selector[nbt[1]] >> 4) & 3; + nrot[2] = (mm->input.block_selector[nbt[2]] >> 4) & 3; + nrot[3] = (mm->input.block_selector[nbt[3]] >> 4) & 3; + nrot[4] = (mm->input.block_selector[nbt[4]] >> 4) & 3; + nrot[5] = (mm->input.block_selector[nbt[5]] >> 4) & 3; + } + #endif } else { #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING if (mm->input.packed_compact == NULL) { @@ -3111,7 +3125,9 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po mesh = mm->default_mesh; if (mm->input.selector) mesh = mm->input.selector[v_off]; - + else if (mm->input.block_selector) + mesh = mm->input.block_selector[bt]; + if (geo <= STBVOX_GEOM_ceil_slope_north_is_bottom) { // this is the simple case, we can just use regular block gen with special vmesh calculated with vheight stbvox_mesh_vertex basevert; @@ -3132,7 +3148,9 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z, 0,0); if (mm->input.selector) { mesh = mm->input.selector[v_off]; - } + } else if (mm->input.block_selector) + mesh = mm->input.block_selector[bt]; + // check if we're going off the end if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) { @@ -3328,7 +3346,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po rotate.overlay = (val >> 2) & 3; //rotate.tex2 = (val >> 4) & 3; rotate.ecolor = (val >> 6) & 3; - } else if (mm->input.selector) { + } else if (mm->input.selector || mm->input.block_selector) { rotate.block = rotate.overlay = rotate.ecolor = simple_rot; } @@ -3352,6 +3370,10 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po mesh = mm->input.selector[v_off]; simple_rot = mesh >> 4; mesh &= 15; + } else if (mm->input.block_selector) { + mesh = mm->input.block_selector[bt]; + simple_rot = mesh >> 4; + mesh &= 15; } // check if we're going off the end @@ -3366,7 +3388,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po rot.overlay = (val >> 2) & 3; //rot.tex2 = (val >> 4) & 3; rot.ecolor = (val >> 6) & 3; - } else if (mm->input.selector) { + } else if (mm->input.selector || mm->input.block_selector) { rot.block = rot.overlay = rot.ecolor = simple_rot; } rot.facerot = 0; From dca0a37ff492200451b4a489276fcd9a065afc2d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 7 Oct 2016 17:36:21 -0700 Subject: [PATCH 386/522] other_libs points to new location --- docs/other_libs.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/other_libs.md diff --git a/docs/other_libs.md b/docs/other_libs.md new file mode 100644 index 0000000..62f379c --- /dev/null +++ b/docs/other_libs.md @@ -0,0 +1 @@ +Moved to https://github.com/nothings/single_file_libs \ No newline at end of file From 5fcd181fae6d5e318bf897473a2ee5a9e2259a51 Mon Sep 17 00:00:00 2001 From: guitarfreak Date: Sat, 8 Oct 2016 04:10:23 +0200 Subject: [PATCH 387/522] Update stb_voxel_render.h --- stb_voxel_render.h | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 17c8fbc..46a4726 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -3010,18 +3010,6 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po nrot[5] = (mm->input.selector[v_off - 1] >> 4) & 3; } #endif - } else if (mm->input.block_selector) { - #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING - if (mm->input.packed_compact == NULL) { - rot = (mm->input.block_selector[bt ] >> 4) & 3; - nrot[0] = (mm->input.block_selector[nbt[0]] >> 4) & 3; - nrot[1] = (mm->input.block_selector[nbt[1]] >> 4) & 3; - nrot[2] = (mm->input.block_selector[nbt[2]] >> 4) & 3; - nrot[3] = (mm->input.block_selector[nbt[3]] >> 4) & 3; - nrot[4] = (mm->input.block_selector[nbt[4]] >> 4) & 3; - nrot[5] = (mm->input.block_selector[nbt[5]] >> 4) & 3; - } - #endif } else { #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING if (mm->input.packed_compact == NULL) { @@ -3346,7 +3334,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po rotate.overlay = (val >> 2) & 3; //rotate.tex2 = (val >> 4) & 3; rotate.ecolor = (val >> 6) & 3; - } else if (mm->input.selector || mm->input.block_selector) { + } else if (mm->input.selector) { rotate.block = rotate.overlay = rotate.ecolor = simple_rot; } @@ -3388,7 +3376,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po rot.overlay = (val >> 2) & 3; //rot.tex2 = (val >> 4) & 3; rot.ecolor = (val >> 6) & 3; - } else if (mm->input.selector || mm->input.block_selector) { + } else if (mm->input.selector) { rot.block = rot.overlay = rot.ecolor = simple_rot; } rot.facerot = 0; From 6a29bcf2a1c00b100558d6b0366fa64f4c0929c7 Mon Sep 17 00:00:00 2001 From: guitarfreak Date: Sat, 8 Oct 2016 04:23:52 +0200 Subject: [PATCH 388/522] Update stb_voxel_render.h --- stb_voxel_render.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 46a4726..32d581c 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -3358,10 +3358,9 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po mesh = mm->input.selector[v_off]; simple_rot = mesh >> 4; mesh &= 15; - } else if (mm->input.block_selector) { + } + if (mm->input.block_selector) { mesh = mm->input.block_selector[bt]; - simple_rot = mesh >> 4; - mesh &= 15; } // check if we're going off the end From 847d288152a2a8cb26b3ae7b68b643eb01cedb0a Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 16 Oct 2016 13:33:21 +0200 Subject: [PATCH 389/522] stb_textedit: fix LINESTART when cursor is at end of buffer and no trailing newline. Stopped using find_charpos(), simpler and faster. --- stb_textedit.h | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 64cf2ca..c68aec6 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -987,58 +987,58 @@ retry: #ifdef STB_TEXTEDIT_K_LINESTART2 case STB_TEXTEDIT_K_LINESTART2: #endif - case STB_TEXTEDIT_K_LINESTART: { - StbFindState find; + case STB_TEXTEDIT_K_LINESTART: stb_textedit_clamp(str, state); stb_textedit_move_to_first(state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - state->cursor = find.first_char; + if (state->single_line) + state->cursor = 0; + else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) + --state->cursor; state->has_preferred_x = 0; break; - } #ifdef STB_TEXTEDIT_K_LINEEND2 case STB_TEXTEDIT_K_LINEEND2: #endif case STB_TEXTEDIT_K_LINEEND: { - StbFindState find; + int n = STB_TEXTEDIT_STRINGLEN(str); stb_textedit_clamp(str, state); stb_textedit_move_to_first(state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - + if (state->single_line) + state->cursor = n; + else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) + ++state->cursor; state->has_preferred_x = 0; - state->cursor = find.first_char + find.length; - if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE) - --state->cursor; break; } #ifdef STB_TEXTEDIT_K_LINESTART2 case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: #endif - case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: { - StbFindState find; + case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: stb_textedit_clamp(str, state); stb_textedit_prep_selection_at_cursor(state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - state->cursor = state->select_end = find.first_char; + if (state->single_line) + state->cursor = 0; + else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) + --state->cursor; + state->select_end = state->cursor; state->has_preferred_x = 0; break; - } #ifdef STB_TEXTEDIT_K_LINEEND2 case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: #endif case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { - StbFindState find; + int n = STB_TEXTEDIT_STRINGLEN(str); stb_textedit_clamp(str, state); stb_textedit_prep_selection_at_cursor(state); - stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - state->has_preferred_x = 0; - state->cursor = find.first_char + find.length; - if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE) - --state->cursor; + if (state->single_line) + state->cursor = n; + else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) + ++state->cursor; state->select_end = state->cursor; + state->has_preferred_x = 0; break; } From 7d0099ecc95ca3b123221bd8bf3228c4197124ff Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 16 Oct 2016 07:58:59 -0700 Subject: [PATCH 390/522] fix bug in stb_connected_components adjacency list updating incorrectly handling avoiding adding the same connection twice --- stb_connected_components.h | 36 +++++++++++++++++++-------------- tests/grid_reachability.c | 41 +++++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/stb_connected_components.h b/stb_connected_components.h index abe2d8e..778b5f9 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -1,4 +1,4 @@ -// stb_connected_components - v0.94 - public domain connected components on grids +// stb_connected_components - v0.95 - public domain connected components on grids // http://github.com/nothings/stb // // Finds connected components on 2D grids for testing reachability between @@ -37,6 +37,7 @@ // // CHANGELOG // +// 0.95 (2016-10-16) Bugfix if multiple clumps in one cluster connect to same clump in another // 0.94 (2016-04-17) Bugfix & optimize worst case (checkerboard & random) // 0.93 (2016-04-16) Reduce memory by 10x for 1Kx1K map; small speedup // 0.92 (2016-04-16) Compute sqrt(N) cluster size by default @@ -201,6 +202,8 @@ typedef unsigned char stbcc__verify_max_clumps[STBCC__MAX_CLUMPS_PER_CLUSTER < ( #define STBCC__MAX_EXITS_PER_CLUSTER (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 for 32x32 #define STBCC__MAX_EXITS_PER_CLUMP (STBCC__CLUSTER_SIZE_X + STBCC__CLUSTER_SIZE_Y) // 64 for 32x32 +#define STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER (STBCC__MAX_EXITS_PER_CLUMP) + // 2^19 * 2^6 => 2^25 exits => 2^26 => 64MB for 1024x1024 // Logic for above on 4x4 grid: @@ -409,7 +412,7 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int // the data into temporary data structures, or just count the sizes, so // for simplicity we do the latter stbcc__cluster *cluster = &g->cluster[cy][cx]; - unsigned char connected[STBCC__MAX_CLUMPS_PER_CLUSTER/8]; + unsigned char connected[STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER][STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER/8]; // 64 x 8 => 1KB unsigned char num_adj[STBCC__MAX_CLUMPS_PER_CLUSTER] = { 0 }; int x = cx * STBCC__CLUSTER_SIZE_X; int y = cy * STBCC__CLUSTER_SIZE_Y; @@ -460,10 +463,11 @@ static void stbcc__build_all_connections_for_cluster(stbcc_grid *g, int cx, int memset(connected, 0, sizeof(connected)); for (k=0; k < n; ++k) { if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { - stbcc__clumpid c = g->clump_for_node[y+j+dy][x+i+dx]; - if (0 == (connected[c>>3] & (1 << (c & 7)))) { - connected[c>>3] |= 1 << (c & 7); - ++num_adj[g->clump_for_node[y+j][x+i]]; + stbcc__clumpid src = g->clump_for_node[y+j][x+i]; + stbcc__clumpid dest = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (connected[src][dest>>3] & (1 << (dest & 7)))) { + connected[src][dest>>3] |= 1 << (dest & 7); + ++num_adj[src]; ++total; } } @@ -707,7 +711,7 @@ static void stbcc__remove_clump_connection(stbcc_grid *g, int x1, int y1, int x2 static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy) { - unsigned char connected[STBCC__MAX_CLUMPS_PER_CLUSTER/8] = { 0 }; + unsigned char connected[STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER][STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER/8] = { 0 }; int x = cx * STBCC__CLUSTER_SIZE_X; int y = cy * STBCC__CLUSTER_SIZE_Y; int step_x, step_y=0, i, j, k, n; @@ -753,10 +757,11 @@ static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, in for (k=0; k < n; ++k) { if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { - stbcc__clumpid c = g->clump_for_node[y+j+dy][x+i+dx]; - if (0 == (connected[c>>3] & (1 << (c & 7)))) { - assert((c>>3) < sizeof(connected)); - connected[c>>3] |= 1 << (c & 7); + stbcc__clumpid src = g->clump_for_node[y+j][x+i]; + stbcc__clumpid dest = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (connected[src][dest>>3] & (1 << (dest & 7)))) { + assert((dest>>3) < sizeof(connected)); + connected[src][dest>>3] |= 1 << (dest & 7); stbcc__add_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); if (g->cluster[cy][cx].rebuild_adjacency) break; @@ -769,7 +774,7 @@ static void stbcc__add_connections_to_adjacent_cluster(stbcc_grid *g, int cx, in static void stbcc__remove_connections_to_adjacent_cluster(stbcc_grid *g, int cx, int cy, int dx, int dy) { - unsigned char disconnected[STBCC__MAX_CLUMPS_PER_CLUSTER/8] = { 0 }; + unsigned char disconnected[STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER][STBCC__MAX_EDGE_CLUMPS_PER_CLUSTER/8] = { 0 }; int x = cx * STBCC__CLUSTER_SIZE_X; int y = cy * STBCC__CLUSTER_SIZE_Y; int step_x, step_y=0, i, j, k, n; @@ -812,9 +817,10 @@ static void stbcc__remove_connections_to_adjacent_cluster(stbcc_grid *g, int cx, for (k=0; k < n; ++k) { if (STBCC__MAP_OPEN(g, x+i, y+j) && STBCC__MAP_OPEN(g, x+i+dx, y+j+dy)) { - stbcc__clumpid c = g->clump_for_node[y+j+dy][x+i+dx]; - if (0 == (disconnected[c>>3] & (1 << (c & 7)))) { - disconnected[c>>3] |= 1 << (c & 7); + stbcc__clumpid src = g->clump_for_node[y+j][x+i]; + stbcc__clumpid dest = g->clump_for_node[y+j+dy][x+i+dx]; + if (0 == (disconnected[src][dest>>3] & (1 << (dest & 7)))) { + disconnected[src][dest>>3] |= 1 << (dest & 7); stbcc__remove_clump_connection(g, x+i, y+j, x+i+dx, y+j+dy); } } diff --git a/tests/grid_reachability.c b/tests/grid_reachability.c index 8314d00..2bb1cd8 100644 --- a/tests/grid_reachability.c +++ b/tests/grid_reachability.c @@ -96,14 +96,24 @@ void write_map(stbcc_grid *g, int w, int h, char *filename) for (i=0; i < w; ++i) { unsigned int c; c = stbcc_get_unique_id(g,i,j); + c = stb_rehash_improved(c)&0xffffff; if (c == STBCC_NULL_UNIQUE_ID) c = 0xff000000; else c = (~c)^0x555555; + if (i % 32 == 0 || j %32 == 0) { + int r = (c >> 16) & 255; + int g = (c >> 8) & 255; + int b = c & 255; + r = (r+130)/2; + g = (g+130)/2; + b = (b+130)/2; + c = 0xff000000 + (r<<16) + (g<<8) + b; + } color[j][i] = c; } } - stbi_write_png(filename, w, h, 4, color, 0); + stbi_write_png(filename, w, h, 4, color, 4*w); } void test_connected(stbcc_grid *g) @@ -159,18 +169,43 @@ int main(int argc, char **argv) map[(stb_rand()%h)*w + stb_rand()%w] ^= 255; #endif + _mkdir("tests/output/stbcc"); + stbi_write_png("tests/output/stbcc/reference.png", w, h, 1, map, 0); //reference(map, w, h); - _mkdir("tests/output/stbcc"); - g = malloc(stbcc_grid_sizeof()); printf("Size: %d\n", stbcc_grid_sizeof()); +#if 0 + memset(map, 0, w*h); + stbcc_init_grid(g, map, w, h); + { + int n; + char **s = stb_stringfile("c:/x/clockwork_update.txt", &n); + write_map(g, w, h, "tests/output/stbcc/base.png"); + for (i=1; i < n; i += 1) { + int x,y,t; + sscanf(s[i], "%d %d %d", &x, &y, &t); + if (i == 571678) + write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_good.png", i)); + stbcc_update_grid(g, x, y, t); + if (i == 571678) + write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_bad.png", i)); + //if (i > 571648 && i <= 571712) + //write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_%06d.png", i)); + } + write_map(g, w, h, stb_sprintf("tests/output/stbcc/clockwork_%06d.png", i-1)); + } + return 0; +#endif + + start_timer("init"); stbcc_init_grid(g, map, w, h); end_timer(); + //g = stb_file("c:/x/clockwork_path.bin", 0); write_map(g, w, h, "tests/output/stbcc/base.png"); for (i=0; i < 5000;) { From 2f4166e91d1e81c8775a2878820187b8b316baf0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 16 Oct 2016 07:59:57 -0700 Subject: [PATCH 391/522] stb_connected_components --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8f77589..6498ab9 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ library | lastest version | category | LoC | description **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **[stb_c_lexer.h](stb_c_lexer.h)** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**[stb_connected_comp...](stb_connected_components.h)** | 0.94 | misc | 1000 | incrementally compute reachability on grids +**[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1006 | incrementally compute reachability on grids **[stb.h](stb.h)** | 2.28 | misc | 14276 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 -Total lines of C code: 47928 +Total lines of C code: 47934 FAQ From f32854c809ab261c07f09f5f27435daadccc2728 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Sep 2016 11:58:00 -0700 Subject: [PATCH 392/522] stb_vorbis: Fix handling of negative numbers in ilog. For negative n, the original code went down the "n < (1<<4)" path and performed an out-of-bounds array access. Fix the code to agree with section 9.2.1 of the Vorbis spec. (Verified by exhaustive testing of all 32-bit ints.) Fixes issue #355. --- stb_vorbis.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index c4f24d5..cb71767 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -986,17 +986,18 @@ static int ilog(int32 n) { static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; + if (n < 0) return 0; // signed n returns 0 + // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) if (n < (1 << 14)) - if (n < (1 << 4)) return 0 + log2_4[n ]; - else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; + if (n < (1 << 4)) return 0 + log2_4[n ]; + else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; else return 10 + log2_4[n >> 10]; else if (n < (1 << 24)) - if (n < (1 << 19)) return 15 + log2_4[n >> 15]; + if (n < (1 << 19)) return 15 + log2_4[n >> 15]; else return 20 + log2_4[n >> 20]; - else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; - else if (n < (1 << 31)) return 30 + log2_4[n >> 30]; - else return 0; // signed n returns 0 + else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; + else return 30 + log2_4[n >> 30]; } #ifndef M_PI From 8c8d735eb7c610811da2cd6efc7a8d59420b4b37 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 12 Aug 2016 13:44:11 -0700 Subject: [PATCH 393/522] stb_image: More input validation in deflate decoder Fixes issue #312. --- stb_image.h | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/stb_image.h b/stb_image.h index a3c1129..d4b623d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3721,6 +3721,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) int hlit = stbi__zreceive(a,5) + 257; int hdist = stbi__zreceive(a,5) + 1; int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; memset(codelength_sizes, 0, sizeof(codelength_sizes)); for (i=0; i < hclen; ++i) { @@ -3730,27 +3731,29 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; n = 0; - while (n < hlit + hdist) { + while (n < ntot) { int c = stbi__zhuffman_decode(a, &z_codelength); if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); if (c < 16) lencodes[n++] = (stbi_uc) c; - else if (c == 16) { - c = stbi__zreceive(a,2)+3; - memset(lencodes+n, lencodes[n-1], c); - n += c; - } else if (c == 17) { - c = stbi__zreceive(a,3)+3; - memset(lencodes+n, 0, c); - n += c; - } else { - STBI_ASSERT(c == 18); - c = stbi__zreceive(a,7)+11; - memset(lencodes+n, 0, c); + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); n += c; } } - if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; return 1; From 02190634c2ff6e3b68fcd99b84cf4acabb70ea2e Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 12 Aug 2016 17:22:46 -0700 Subject: [PATCH 394/522] stb_image: Overflow checking for image allocs. Adds some helpers that check whether a product of multiple factors (that need to be non-negative: this is enforced) summed with another non-negative value overflows when performed as int. Since stb_image mostly works in ints, this seems like the safest route. Limits size of images to 2GB but several of the decoders already enforce this limit (or even lower ones). Also adds wrappers for malloc that combine a mul-add-with- overflow-check with the actual malloc, and return NULL on failure. Then use them when allocating something that is the product of multiple factors. For image formats, also add a top-level "is this too big?" check that gives a more useful error message; otherwise, the failed mallocs result in an "out of memory" error. The idea is that the top-level checks should be the primary way to catch these bugs (and produce a useful error message). But a misleading error message is still vastly preferable to a buffer overflow exploit. Fixes issues #310, #313, #314, #318. (Verified with the provided test images) Along the way, this fixes a previously unnoticed bug in ldr_to_hdr / hdr_to_ldr (missing NULL check); these functions are called with the result of an image decoder, so NULLs can definitely happen. Another bug noticed along the way is that handling of interlaced 16-bit PNGs was incorrect. Fixing this (along with the previous modifications) fixes issue #311. Yet another bug noticed during this change is that reduce_png did not check the right pointer during its out of memory check. Fix that too. --- stb_image.h | 156 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 131 insertions(+), 25 deletions(-) diff --git a/stb_image.h b/stb_image.h index d4b623d..2a6c45a 100644 --- a/stb_image.h +++ b/stb_image.h @@ -566,6 +566,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch #include // ptrdiff_t on osx #include #include +#include #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) #include // ldexp @@ -900,6 +901,77 @@ static void *stbi__malloc(size_t size) return STBI_MALLOC(size); } +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} + // stbi__err - error // stbi__errpf - error returning pointer to float // stbi__errpuc - error returning pointer to unsigned char @@ -1346,7 +1418,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - good = (unsigned char *) stbi__malloc(req_comp * x * y); + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); if (good == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); @@ -1386,7 +1458,9 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) { int i,k,n; - float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; @@ -1406,7 +1480,9 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) { int i,k,n; - stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; @@ -2738,7 +2814,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) if (scan != STBI__SCAN_load) return 1; - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); for (i=0; i < s->img_n; ++i) { if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; @@ -2750,6 +2826,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) z->img_v_max = v_max; z->img_mcu_w = h_max * 8; z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; @@ -2761,9 +2838,12 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) // the bogus oversized data from using interleaved MCUs and their // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; - z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); if (z->img_comp[i].raw_data == NULL) { for(--i; i >= 0; --i) { @@ -2776,9 +2856,10 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); z->img_comp[i].linebuf = NULL; if (z->progressive) { - z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; - z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; - z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); } else { z->img_comp[i].coeff = 0; @@ -3368,7 +3449,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } // can't error after this so, this is safe - output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } // now go ahead and resample @@ -4019,7 +4100,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r int width = x; STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); @@ -4217,13 +4298,15 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) { + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; stbi_uc *final; int p; if (!interlaced) return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); // de-interlacing - final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; @@ -4243,8 +4326,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3 for (i=0; i < x; ++i) { int out_y = j*yspc[p]+yorig[p]; int out_x = i*xspc[p]+xorig[p]; - memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, - a->out + (j*x+i)*out_n, out_n); + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); } } STBI_FREE(a->out); @@ -4312,7 +4395,7 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; stbi_uc *p, *temp_out, *orig = a->out; - p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); if (p == NULL) return stbi__err("outofmem", "Out of memory"); // between here and free(out) below, exitting would leak @@ -4354,9 +4437,10 @@ static int stbi__reduce_png(stbi__png *p) if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data reduced = (stbi_uc *)stbi__malloc(img_len); - if (p == NULL) return stbi__err("outofmem", "Out of memory"); + if (reduced == NULL) return stbi__err("outofmem", "Out of memory"); - for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling p->out = reduced; STBI_FREE(orig); @@ -4846,7 +4930,11 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int else target = s->img_n; // if they want monochrome, we'll post-convert - out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (info.bpp < 16) { int z=0; @@ -5146,7 +5234,10 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int *y = tga_height; if (comp) *comp = tga_comp; - tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); // skip to the data's starting position (offset usually = 0) @@ -5165,7 +5256,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int // any data to skip? (offset usually = 0) stbi__skip(s, tga_palette_start ); // load the palette - tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp ); + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); if (!tga_palette) { STBI_FREE(tga_data); return stbi__errpuc("outofmem", "Out of memory"); @@ -5365,8 +5456,12 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int if (compression > 1) return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + // Create the destination image. - out = (stbi_uc *) stbi__malloc(4 * w*h); + out = (stbi_uc *) stbi__malloc_mad3(4, w, h, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); pixelCount = w*h; @@ -5668,14 +5763,14 @@ static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int re x = stbi__get16be(s); y = stbi__get16be(s); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); - if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); stbi__get32be(s); //skip `ratio' stbi__get16be(s); //skip `fields' stbi__get16be(s); //skip `pad' // intermediate buffer is RGBA - result = (stbi_uc *) stbi__malloc(x*y*4); + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); memset(result, 0xff, x*y*4); if (!stbi__pic_load_core(s,x,y,comp, result)) { @@ -5934,8 +6029,11 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(g->w, g->h, 4, 0)) + return stbi__errpuc("too large", "GIF too large"); + prev_out = g->out; - g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->out = (stbi_uc *) stbi__malloc_mad3(4, g->w, g->h, 0); if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); switch ((g->eflags & 0x1C) >> 2) { @@ -6182,8 +6280,13 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re if (comp) *comp = 3; if (req_comp == 0) req_comp = 3; + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + // Read data - hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); // Load image data // image data is stored as some number of sca @@ -6431,7 +6534,10 @@ static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int *y = s->img_y; *comp = s->img_n; - out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y); + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); stbi__getn(s, out, s->img_n * s->img_x * s->img_y); From 62f372754f8dfb1bc5ae9e25fdc3f0c75fb08001 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 12 Aug 2016 17:31:53 -0700 Subject: [PATCH 395/522] stb_image: Fix HDR/PSD RLE decoders. Runs need to be bounds checked. Fixes issues #315, #317. --- stb_image.h | 89 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/stb_image.h b/stb_image.h index 2a6c45a..3ae6c48 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5392,11 +5392,49 @@ static int stbi__psd_test(stbi__context *s) return r; } +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) { - int pixelCount; + int pixelCount; int channelCount, compression; - int channel, i, count, len; + int channel, i; int bitdepth; int w,h; stbi_uc *out; @@ -5493,34 +5531,9 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int *p = (channel == 3 ? 255 : 0); } else { // Read the RLE data. - count = 0; - while (count < pixelCount) { - len = stbi__get8(s); - if (len == 128) { - // No-op. - } else if (len < 128) { - // Copy next len+1 bytes literally. - len++; - count += len; - while (len) { - *p = stbi__get8(s); - p += 4; - len--; - } - } else if (len > 128) { - stbi_uc val; - // Next -len+1 bytes in the dest are replicated from next source byte. - // (Interpret len as a negative 8-bit int.) - len ^= 0x0FF; - len += 2; - val = stbi__get8(s); - count += len; - while (len) { - *p = val; - p += 4; - len--; - } - } + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); } } } @@ -6325,20 +6338,29 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re len <<= 8; len |= stbi__get8(s); if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } - if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } for (k = 0; k < 4; ++k) { + int nleft; i = 0; - while (i < width) { + while ((nleft = width - i) > 0) { count = stbi__get8(s); if (count > 128) { // Run value = stbi__get8(s); count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = value; } else { // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = stbi__get8(s); } @@ -6347,7 +6369,8 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re for (i=0; i < width; ++i) stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); } - STBI_FREE(scanline); + if (scanline) + STBI_FREE(scanline); } return hdr_data; From 6b66033e18c22de830b9ea599bf448843fd104cf Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 12 Aug 2016 17:46:43 -0700 Subject: [PATCH 396/522] stb_image: Fix memory leak and missing out-of-mem check. stbi__process_frame_header had two bugs when dealing with progressive JPEGs: 1. when malloc failed allocating raw_data, previous components' raw_coeff didn't get freed 2. no out-of-memory check in raw_coeff allocation Fix both and share a bit more cleanup code in general. --- stb_image.h | 59 +++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3ae6c48..82e7081 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2777,6 +2777,28 @@ static int stbi__process_scan_header(stbi__jpeg *z) return 1; } +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + static int stbi__process_frame_header(stbi__jpeg *z, int scan) { stbi__context *s = z->s; @@ -2843,27 +2865,22 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) // so these muls can't overflow with 32-bit ints (which we require) z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); - - if (z->img_comp[i].raw_data == NULL) { - for(--i; i >= 0; --i) { - STBI_FREE(z->img_comp[i].raw_data); - z->img_comp[i].raw_data = NULL; - } - return stbi__err("outofmem", "Out of memory"); - } + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); // align blocks for idct using mmx/sse z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); - z->img_comp[i].linebuf = NULL; if (z->progressive) { // w2, h2 are multiples of 8 (see above) z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); - } else { - z->img_comp[i].coeff = 0; - z->img_comp[i].raw_coeff = 0; } } @@ -3369,23 +3386,7 @@ static void stbi__setup_jpeg(stbi__jpeg *j) // clean up the temporary component buffers static void stbi__cleanup_jpeg(stbi__jpeg *j) { - int i; - for (i=0; i < j->s->img_n; ++i) { - if (j->img_comp[i].raw_data) { - STBI_FREE(j->img_comp[i].raw_data); - j->img_comp[i].raw_data = NULL; - j->img_comp[i].data = NULL; - } - if (j->img_comp[i].raw_coeff) { - STBI_FREE(j->img_comp[i].raw_coeff); - j->img_comp[i].raw_coeff = 0; - j->img_comp[i].coeff = 0; - } - if (j->img_comp[i].linebuf) { - STBI_FREE(j->img_comp[i].linebuf); - j->img_comp[i].linebuf = NULL; - } - } + stbi__free_jpeg_components(j, j->s->img_n, 0); } typedef struct From 5d9423f8fd91744269c7413b7352778324f627bb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 25 Oct 2016 08:50:44 -0700 Subject: [PATCH 397/522] fix -Wcast-qual in stb_rect_pack, stb_textedit, stb_truetype --- stb_rect_pack.h | 12 ++++---- stb_textedit.h | 18 +++++++++-- stb_truetype.h | 82 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 75 insertions(+), 37 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index 421ba40..b55d6b4 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -510,8 +510,8 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i static int rect_height_compare(const void *a, const void *b) { - stbrp_rect *p = (stbrp_rect *) a; - stbrp_rect *q = (stbrp_rect *) b; + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; if (p->h > q->h) return -1; if (p->h < q->h) @@ -521,8 +521,8 @@ static int rect_height_compare(const void *a, const void *b) static int rect_width_compare(const void *a, const void *b) { - stbrp_rect *p = (stbrp_rect *) a; - stbrp_rect *q = (stbrp_rect *) b; + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; if (p->w > q->w) return -1; if (p->w < q->w) @@ -532,8 +532,8 @@ static int rect_width_compare(const void *a, const void *b) static int rect_original_order(const void *a, const void *b) { - stbrp_rect *p = (stbrp_rect *) a; - stbrp_rect *q = (stbrp_rect *) b; + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); } diff --git a/stb_textedit.h b/stb_textedit.h index 64cf2ca..14491db 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -671,9 +671,8 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) } // API paste: replace existing selection with passed-in text -static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) +static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) { - STB_TEXTEDIT_CHARTYPE *text = (STB_TEXTEDIT_CHARTYPE *) ctext; // if there's a selection, the paste should delete it stb_textedit_clamp(str, state); stb_textedit_delete_selection(str,state); @@ -1312,4 +1311,19 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl { stb_textedit_clear_state(state, is_single_line); } + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) +{ + return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + #endif//STB_TEXTEDIT_IMPLEMENTATION diff --git a/stb_truetype.h b/stb_truetype.h index d360d60..1a8f9ca 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -593,9 +593,9 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, stbtt_aligned_quad *q, // output: quad to draw int align_to_integer); -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look @@ -968,26 +968,15 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define ttCHAR(p) (* (stbtt_int8 *) (p)) #define ttFixed(p) ttLONG(p) -#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) - - #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) - #define ttSHORT(p) (* (stbtt_int16 *) (p)) - #define ttULONG(p) (* (stbtt_uint32 *) (p)) - #define ttLONG(p) (* (stbtt_int32 *) (p)) - -#else - - static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - -#endif +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) -static int stbtt__isfont(const stbtt_uint8 *font) +static int stbtt__isfont(stbtt_uint8 *font) { // check the version number if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 @@ -1011,7 +1000,7 @@ static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, return 0; } -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) { // if it's just a font, there's only one valid index if (stbtt__isfont(font_collection)) @@ -1030,9 +1019,8 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, return -1; } -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) { - stbtt_uint8 *data = (stbtt_uint8 *) data2; stbtt_uint32 cmap, t; stbtt_int32 i,numTables; @@ -2532,7 +2520,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned ch // // This is SUPER-CRAPPY packing to keep source code small -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake @@ -2862,7 +2850,7 @@ static float stbtt__oversample_shift(int oversample) } // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k; @@ -2891,7 +2879,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon } // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k, return_value = 1; @@ -3060,7 +3048,7 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2) +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) { stbtt_int32 i=0; @@ -3099,9 +3087,9 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 return i; } -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { - return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2); + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); } // returns results in whatever encoding you request... but note that 2-byte encodings @@ -3157,7 +3145,7 @@ static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, return 1; } else if (matchlen < nlen && name[matchlen] == ' ') { ++matchlen; - if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) return 1; } } else { @@ -3203,7 +3191,7 @@ static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *nam return 0; } -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) { stbtt_int32 i; for (i=0;;++i) { @@ -3214,6 +3202,42 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const } } +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + #endif // STB_TRUETYPE_IMPLEMENTATION From 996ccf21590a79f3efb17dab7093614b58c7187c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 25 Oct 2016 08:53:48 -0700 Subject: [PATCH 398/522] update version numbers --- README.md | 8 ++++---- stb_rect_pack.h | 3 ++- stb_textedit.h | 3 ++- stb_truetype.h | 12 ++++-------- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 6498ab9..840f061 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,12 @@ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5399 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_image.h](stb_image.h)** | 2.12 | graphics | 6755 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.11 | graphics | 3267 | parse, decode, and rasterize characters from truetype fonts +**[stb_truetype.h](stb_truetype.h)** | 1.12 | graphics | 3287 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality -**[stb_rect_pack.h](stb_rect_pack.h)** | 0.09 | graphics | 582 | simple 2D rectangle packer with decent quality +**[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 583 | simple 2D rectangle packer with decent quality **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**[stb_textedit.h](stb_textedit.h)** | 1.9 | user interface | 1315 | guts of a text editor for games etc implementing them from scratch +**[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1330 | guts of a text editor for games etc implementing them from scratch **[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features **[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) @@ -28,7 +28,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 -Total lines of C code: 47934 +Total lines of C code: 47970 FAQ diff --git a/stb_rect_pack.h b/stb_rect_pack.h index b55d6b4..c75527d 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.09 - public domain - rectangle packing +// stb_rect_pack.h - v0.10 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -32,6 +32,7 @@ // // Version history: // +// 0.10 (2016-10-25) remove cast-away-const to avoid warnings // 0.09 (2016-08-27) fix compiler warnings // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) diff --git a/stb_textedit.h b/stb_textedit.h index 14491db..27a6993 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// stb_textedit.h - v1.9 - public domain - Sean Barrett +// stb_textedit.h - v1.10 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -31,6 +31,7 @@ // // VERSION HISTORY // +// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual // 1.9 (2016-08-27) customizable move-by-word // 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.7 (2015-09-13) change y range handling in case baseline is non-0 diff --git a/stb_truetype.h b/stb_truetype.h index 1a8f9ca..88a2da1 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,5 +1,5 @@ -// stb_truetype.h - v1.11 - public domain -// authored from 2009-2015 by Sean Barrett / RAD Game Tools +// stb_truetype.h - v1.12 - public domain +// authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: // parse files @@ -51,6 +51,7 @@ // // VERSION HISTORY // +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly @@ -60,12 +61,6 @@ // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); // fixed an assert() bug in the new rasterizer // replace assert() with STBTT_assert() in new rasterizer -// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) -// also more precise AA rasterizer, except if shapes overlap -// remove need for STBTT_sort -// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC -// 1.04 (2015-04-15) typo in example -// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes // // Full history can be found at the end of this file. // @@ -3243,6 +3238,7 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // FULL VERSION HISTORY // +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) allow user-defined fabs() replacement // fix memory leak if fontsize=0.0 From cd93a5de110c2045278606cee37829304ed36689 Mon Sep 17 00:00:00 2001 From: snake5 Date: Sat, 26 Nov 2016 16:45:40 +0200 Subject: [PATCH 399/522] added basic 3Dc support --- stb_dxt.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stb_dxt.h b/stb_dxt.h index 0a8b34a..31b36d4 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -32,6 +32,7 @@ #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower. void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode); +void stb_compress_3dc_block_rgxx8(unsigned char *dest, const unsigned char *src, int mode); #define STB_COMPRESS_DXT_BLOCK #ifdef STB_DXT_IMPLEMENTATION @@ -625,6 +626,12 @@ void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int a stb__CompressColorBlock(dest,(unsigned char*) src,mode); } + +void stb_compress_3dc_block_rgxx8(unsigned char *dest, const unsigned char *src, int mode) +{ + stb__CompressAlphaBlock(dest,(unsigned char*) src - 3,mode); + stb__CompressAlphaBlock(dest + 8,(unsigned char*) src - 2,mode); +} #endif // STB_DXT_IMPLEMENTATION #endif // STB_INCLUDE_STB_DXT_H From a2defc3d7a273416b306ce2cf2bee49431957f31 Mon Sep 17 00:00:00 2001 From: jon Date: Mon, 28 Nov 2016 16:05:39 -0600 Subject: [PATCH 400/522] added support for RGBE header HDR files --- stb_image.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index a3c1129..f9ed5a6 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6147,10 +6147,11 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re int len; unsigned char count, value; int i, j, k, c1,c2, z; - + const char *headerToken; // Check identifier - if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) return stbi__errpf("not HDR", "Corrupt HDR image"); // Parse header From 2a170daee5dd339bc8f3f81024a97710935c360f Mon Sep 17 00:00:00 2001 From: jon Date: Mon, 28 Nov 2016 16:24:11 -0600 Subject: [PATCH 401/522] warning fixes, more RGBE fix --- stb_image.h | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/stb_image.h b/stb_image.h index f9ed5a6..e095fb8 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4500,7 +4500,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; if (z->depth == 16) { - for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is } else { for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger } @@ -5079,16 +5079,16 @@ errorEnd: // read 16bit value and convert to 24bit RGB void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) { - stbi__uint16 px = stbi__get16le(s); + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); stbi__uint16 fiveBitMask = 31; // we have 3 channels with 5bits each int r = (px >> 10) & fiveBitMask; int g = (px >> 5) & fiveBitMask; int b = px & fiveBitMask; // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later - out[0] = (r * 255)/31; - out[1] = (g * 255)/31; - out[2] = (b * 255)/31; + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); // some people claim that the most significant bit might be used for alpha // (possibly if an alpha-bit is set in the "image descriptor byte") @@ -6069,20 +6069,24 @@ static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) // Radiance RGBE HDR loader // originally by Nicolas Schulz #ifndef STBI_NO_HDR -static int stbi__hdr_test_core(stbi__context *s) +static int stbi__hdr_test_core(stbi__context *s, const char *signature) { - const char *signature = "#?RADIANCE\n"; int i; for (i=0; signature[i]; ++i) if (stbi__get8(s) != signature[i]) - return 0; + return 0; + stbi__rewind(s); return 1; } static int stbi__hdr_test(stbi__context* s) { - int r = stbi__hdr_test_core(s); + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } return r; } From 239a6718e185d3ecbf3da6329db0c0d94ee6d7ec Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 29 Nov 2016 03:03:07 -0800 Subject: [PATCH 402/522] rename stbi_load parameters to reduce confusion --- stb_image.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/stb_image.h b/stb_image.h index a3c1129..38a9f3d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -238,10 +238,10 @@ publish, and distribute this file as you see fit. // stbi_image_free(data) // // Standard parameters: -// int *x -- outputs image width in pixels -// int *y -- outputs image height in pixels -// int *comp -- outputs # of image components in image file -// int req_comp -- if non-zero, # of image components requested in result +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result // // The return value from an image loader is an 'unsigned char *' which points // to the pixel data, or NULL on an allocation failure or if the image is @@ -406,6 +406,7 @@ enum }; typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; #ifdef __cplusplus extern "C" { @@ -433,22 +434,24 @@ typedef struct int (*eof) (void *user); // returns nonzero if we are at end of file/data } stbi_io_callbacks; -STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); -STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp); -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO -STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); // for stbi_load_from_file, file pointer is left pointing immediately after image #endif +//STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + #ifndef STBI_NO_LINEAR - STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); - STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); - STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO - STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif #endif From e0700d8e2c1f2a8c8666f9776063e5f956b38230 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 29 Nov 2016 04:13:17 -0800 Subject: [PATCH 403/522] 16-bit png changes --- stb_image.h | 415 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 291 insertions(+), 124 deletions(-) diff --git a/stb_image.h b/stb_image.h index 38a9f3d..6c67db3 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.12 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.13 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -146,6 +146,7 @@ Latest revision history: + 2.13 (2016-11-29) experimental 16-bit API, only for PNG so far 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; @@ -157,21 +158,6 @@ 2.07 (2015-09-13) partial animated GIF support limited 16-bit PSD support minor bugs, code cleanup, and compiler warnings - 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value - 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning - 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit - 2.03 (2015-04-12) additional corruption checking - stbi_set_flip_vertically_on_load - fix NEON support; fix mingw support - 2.02 (2015-01-19) fix incorrect assert, fix warning - 2.01 (2015-01-17) fix various warnings - 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG - 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD - progressive JPEG - PGM/PPM support - STBI_MALLOC,STBI_REALLOC,STBI_FREE - STBI_NO_*, STBI_ONLY_* - GIF bugfix See end of file for full revision history. @@ -434,17 +420,35 @@ typedef struct int (*eof) (void *user); // returns nonzero if we are at end of file/data } stbi_io_callbacks; +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO -STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); // for stbi_load_from_file, file pointer is left pointing immediately after image #endif -//STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +//////////////////////////////////// +// +// 16-bits-per-channel interface +// +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif +// @TODO the other variants + +//////////////////////////////////// +// +// float-per-channel interface +// #ifndef STBI_NO_LINEAR STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); @@ -830,57 +834,69 @@ static void stbi__rewind(stbi__context *s) s->img_buffer_end = s->img_buffer_original_end; } +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int channel_order; +} stbi__result_info; + #ifndef STBI_NO_JPEG static int stbi__jpeg_test(stbi__context *s); -static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNG static int stbi__png_test(stbi__context *s); -static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_BMP static int stbi__bmp_test(stbi__context *s); -static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_TGA static int stbi__tga_test(stbi__context *s); -static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PSD static int stbi__psd_test(stbi__context *s); -static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_HDR static int stbi__hdr_test(stbi__context *s); -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PIC static int stbi__pic_test(stbi__context *s); -static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_GIF static int stbi__gif_test(stbi__context *s); -static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNM static int stbi__pnm_test(stbi__context *s); -static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); #endif @@ -938,33 +954,37 @@ STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) stbi__vertically_flip_on_load = flag_true_if_should_flip; } -static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + #ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PNG - if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_BMP - if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_GIF - if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PSD - if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PIC - if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PNM - if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { - float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); } #endif @@ -972,35 +992,118 @@ static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *com #ifndef STBI_NO_TGA // test tga last because it's a crappy test! if (stbi__tga_test(s)) - return stbi__tga_load(s,x,y,comp,req_comp); + return stbi__tga_load(s,x,y,comp,req_comp, ri); #endif return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); } -static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) { - unsigned char *result = stbi__load_main(s, x, y, comp, req_comp); + int i; + int img_len = w * h * channels; + stbi_uc *reduced; - if (stbi__vertically_flip_on_load && result != NULL) { + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *reduced; + + reduced = (stbi__uint16 *) stbi__malloc(img_len*2); + if (reduced == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return reduced; +} + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + // @TODO: special case RGB-to-Y for 8-bit-to-16-bit case in postprocess_16bit + + if (stbi__vertically_flip_on_load) { int w = *x, h = *y; - int depth = req_comp ? req_comp : *comp; + int channels = req_comp ? req_comp : *comp; int row,col,z; - stbi_uc temp; + stbi_uc *image = (stbi_uc *) result; // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once for (row = 0; row < (h>>1); row++) { for (col = 0; col < w; col++) { - for (z = 0; z < depth; z++) { - temp = result[(row * w + col) * depth + z]; - result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; - result[((h - row - 1) * w + col) * depth + z] = temp; + for (z = 0; z < channels; z++) { + stbi_uc temp = image[(row * w + col) * channels + z]; + image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z]; + image[((h - row - 1) * w + col) * channels + z] = temp; } } } } - return result; + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y for 8-bit-to-16-bit case to keep more precision (look at function, discards 8 bits) + + if (stbi__vertically_flip_on_load) { + int w = *x, h = *y; + int channels = req_comp ? req_comp : *comp; + int row,col,z; + stbi__uint16 *image = (stbi__uint16 *) result; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < channels; z++) { + stbi__uint16 temp = image[(row * w + col) * channels + z]; + image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z]; + image[((h - row - 1) * w + col) * channels + z] = temp; + } + } + } + } + + return (stbi__uint16 *) result; } #ifndef STBI_NO_HDR @@ -1056,27 +1159,52 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req unsigned char *result; stbi__context s; stbi__start_file(&s,f); - result = stbi__load_flip(&s,x,y,comp,req_comp); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); if (result) { // need to 'unget' all the characters in the IO buffer fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); } return result; } + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + #endif //!STBI_NO_STDIO STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_mem(&s,buffer,len); - return stbi__load_flip(&s,x,y,comp,req_comp); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__load_flip(&s,x,y,comp,req_comp); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } #ifndef STBI_NO_LINEAR @@ -1085,13 +1213,14 @@ static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int unsigned char *data; #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { - float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp); + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); if (hdr_data) stbi__float_postprocess(hdr_data,x,y,comp,req_comp); return hdr_data; } #endif - data = stbi__load_flip(s, x, y, comp, req_comp); + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); if (data) return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); @@ -1359,26 +1488,75 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r unsigned char *src = data + j * x * img_n ; unsigned char *dest = good + j * x * req_comp; - #define COMBO(a,b) ((a)*8+(b)) - #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros - switch (COMBO(img_n, req_comp)) { - CASE(1,2) dest[0]=src[0], dest[1]=255; break; - CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; - CASE(2,1) dest[0]=src[0]; break; - CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; - CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; - CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; - CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; - CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) dest[0]=src[0], dest[1]=255; break; + STBI__CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + STBI__CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + STBI__CASE(2,1) dest[0]=src[0]; break; + STBI__CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + STBI__CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + STBI__CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + STBI__CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + STBI__CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + STBI__CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + STBI__CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + STBI__CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; default: STBI_ASSERT(0); } - #undef CASE + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) dest[0]=src[0], dest[1]=0xffff; break; + STBI__CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + STBI__CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; break; + STBI__CASE(2,1) dest[0]=src[0]; break; + STBI__CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + STBI__CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + STBI__CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; break; + STBI__CASE(3,1) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); break; + STBI__CASE(3,2) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; break; + STBI__CASE(4,1) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); break; + STBI__CASE(4,2) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; break; + STBI__CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE } STBI_FREE(data); @@ -3427,7 +3605,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } } -static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); @@ -4084,37 +4262,37 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r // this is a little gross, so that we don't switch per-pixel or per-component if (depth < 8 || img_n == out_n) { int nk = (width - 1)*filter_bytes; - #define CASE(f) \ + #define STBI__CASE(f) \ case f: \ for (k=0; k < nk; ++k) switch (filter) { // "none" filter turns into a memcpy here; make that explicit. case STBI__F_none: memcpy(cur, raw, nk); break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; - CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; + STBI__CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; + STBI__CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + STBI__CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; + STBI__CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; + STBI__CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; + STBI__CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; } - #undef CASE + #undef STBI__CASE raw += nk; } else { STBI_ASSERT(img_n+1 == out_n); - #define CASE(f) \ + #define STBI__CASE(f) \ case f: \ for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ for (k=0; k < filter_bytes; ++k) switch (filter) { - CASE(STBI__F_none) cur[k] = raw[k]; break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break; - CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break; + STBI__CASE(STBI__F_none) cur[k] = raw[k]; break; + STBI__CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break; + STBI__CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + STBI__CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break; + STBI__CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break; + STBI__CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break; + STBI__CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break; } - #undef CASE + #undef STBI__CASE // the loop above sets the high byte of the pixels' alpha, but for // 16 bit png files we also need the low byte set. we'll do that here. @@ -4344,26 +4522,6 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int return 1; } -static int stbi__reduce_png(stbi__png *p) -{ - int i; - int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n; - stbi_uc *reduced; - stbi__uint16 *orig = (stbi__uint16*)p->out; - - if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data - - reduced = (stbi_uc *)stbi__malloc(img_len); - if (p == NULL) return stbi__err("outofmem", "Out of memory"); - - for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling - - p->out = reduced; - STBI_FREE(orig); - - return 1; -} - static int stbi__unpremultiply_on_load = 0; static int stbi__de_iphone_flag = 0; @@ -4590,20 +4748,19 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) } } -static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp) +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) { - unsigned char *result=NULL; + void *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - if (p->depth == 16) { - if (!stbi__reduce_png(p)) { - return result; - } - } + ri->bits_per_channel = p->depth; result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { - result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); p->s->img_out_n = req_comp; if (result == NULL) return result; } @@ -4618,11 +4775,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req return result; } -static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi__png p; p.s = s; - return stbi__do_png(&p, x,y,comp,req_comp); + return stbi__do_png(&p, x,y,comp,req_comp, ri); } static int stbi__png_test(stbi__context *s) @@ -4810,7 +4967,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) } -static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; unsigned int mr=0,mg=0,mb=0,ma=0, all_a; @@ -4818,6 +4975,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int int psize=0,i,j,width; int flip_vertically, pad, target; stbi__bmp_data info; + STBI_NOTUSED(ri); info.all_a = 255; if (stbi__bmp_parse_header(s, &info) == NULL) @@ -5099,7 +5257,7 @@ void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) // so let's treat all 15 and 16bit TGAs as RGB with no alpha. } -static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { // read in the TGA header stuff int tga_offset = stbi__get8(s); @@ -5125,6 +5283,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; + STBI_NOTUSED(ri); // do a tiny bit of precessing if ( tga_image_type >= 8 ) @@ -5301,7 +5460,8 @@ static int stbi__psd_test(stbi__context *s) return r; } -static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +// @TODO: return 16-bit PSD data to 16-bit interface +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { int pixelCount; int channelCount, compression; @@ -5309,6 +5469,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int int bitdepth; int w,h; stbi_uc *out; + STBI_NOTUSED(ri); // Check identifier if (stbi__get32be(s) != 0x38425053) // "8BPS" @@ -5657,10 +5818,11 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c return result; } -static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp) +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) { stbi_uc *result; int i, x,y; + STBI_NOTUSED(ri); for (i=0; i<92; ++i) stbi__get8(s); @@ -6042,11 +6204,12 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i STBI_NOTUSED(req_comp); } -static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *u = 0; stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); memset(g, 0, sizeof(*g)); + STBI_NOTUSED(ri); u = stbi__gif_load_next(s, g, comp, req_comp); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker @@ -6139,7 +6302,7 @@ static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) } } -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { char buffer[STBI__HDR_BUFLEN]; char *token; @@ -6150,7 +6313,7 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re int len; unsigned char count, value; int i, j, k, c1,c2, z; - + STBI_NOTUSED(ri); // Check identifier if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) @@ -6422,11 +6585,14 @@ static int stbi__pnm_test(stbi__context *s) return 1; } -static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; + STBI_NOTUSED(ri); + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) return 0; + *x = s->img_x; *y = s->img_y; *comp = s->img_n; @@ -6596,6 +6762,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) allocate large structures on the stack remove white matting for transparent PSD From 07fefa384a55bda00039454a5e164f3f20093668 Mon Sep 17 00:00:00 2001 From: IntellectualKitty Date: Wed, 30 Nov 2016 13:24:38 -0700 Subject: [PATCH 404/522] Return all_rects_packed status from stbrp_pack_rects. --- stb_rect_pack.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index c75527d..851fa1b 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -77,7 +77,7 @@ typedef int stbrp_coord; typedef unsigned short stbrp_coord; #endif -STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); +STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); // Assign packed locations to rectangles. The rectangles are of type // 'stbrp_rect' defined below, stored in the array 'rects', and there // are 'num_rects' many of them. @@ -98,6 +98,9 @@ STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int // arrays will probably produce worse packing results than calling it // a single time with the full rectangle array, but the option is // available. +// +// The function returns 1 if all of the rectangles were successfully +// packed and 0 otherwise. struct stbrp_rect { @@ -544,9 +547,9 @@ static int rect_original_order(const void *a, const void *b) #define STBRP__MAXVAL 0xffff #endif -STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) +STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { - int i; + int i, all_rects_packed = 1; // we use the 'was_packed' field internally to allow sorting/unsorting for (i=0; i < num_rects; ++i) { @@ -576,8 +579,14 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n // unsort STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); - // set was_packed flags + // set was_packed flags and all_rects_packed status for (i=0; i < num_rects; ++i) - rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + { + if (!(rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL))) + all_rects_packed = 0; + } + + // return the all_rects_packed status + return all_rects_packed; } #endif From 77363995175908b304525f2cc2b17180f2fdad96 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 4 Dec 2016 05:13:58 -0800 Subject: [PATCH 405/522] return 16-bit PSDs through 16-bit API (untested) --- stb_image.h | 100 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 32 deletions(-) diff --git a/stb_image.h b/stb_image.h index 6c67db3..5a3febb 100644 --- a/stb_image.h +++ b/stb_image.h @@ -843,6 +843,7 @@ enum typedef struct { int bits_per_channel; + int num_channels; int channel_order; } stbi__result_info; @@ -872,7 +873,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); #ifndef STBI_NO_PSD static int stbi__psd_test(stbi__context *s); -static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); #endif @@ -954,11 +955,12 @@ STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) stbi__vertically_flip_on_load = flag_true_if_should_flip; } -static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; #ifndef STBI_NO_JPEG if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); @@ -973,7 +975,7 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PSD - if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri); + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); #endif #ifndef STBI_NO_PIC if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); @@ -1033,7 +1035,7 @@ static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int chan static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; - void *result = stbi__load_main(s, x, y, comp, req_comp, &ri); + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); if (result == NULL) return NULL; @@ -1045,7 +1047,6 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, } // @TODO: move stbi__convert_format to here - // @TODO: special case RGB-to-Y for 8-bit-to-16-bit case in postprocess_16bit if (stbi__vertically_flip_on_load) { int w = *x, h = *y; @@ -1071,7 +1072,7 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; - void *result = stbi__load_main(s, x, y, comp, req_comp, &ri); + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); if (result == NULL) return NULL; @@ -1083,7 +1084,7 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, } // @TODO: move stbi__convert_format16 to here - // @TODO: special case RGB-to-Y for 8-bit-to-16-bit case to keep more precision (look at function, discards 8 bits) + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision if (stbi__vertically_flip_on_load) { int w = *x, h = *y; @@ -5461,7 +5462,7 @@ static int stbi__psd_test(stbi__context *s) } // @TODO: return 16-bit PSD data to 16-bit interface -static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { int pixelCount; int channelCount, compression; @@ -5527,7 +5528,13 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req return stbi__errpuc("bad compression", "PSD has an unknown compression format"); // Create the destination image. - out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc(4 * w*h * 2); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); pixelCount = w*h; @@ -5597,44 +5604,73 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req // Read the data by channel. for (channel = 0; channel < 4; channel++) { - stbi_uc *p; - - p = out + channel; if (channel >= channelCount) { // Fill this channel with default data. - stbi_uc val = channel == 3 ? 255 : 0; - for (i = 0; i < pixelCount; i++, p += 4) - *p = val; - } else { - // Read the data. - if (bitdepth == 16) { - for (i = 0; i < pixelCount; i++, p += 4) - *p = (stbi_uc) (stbi__get16be(s) >> 8); + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi_uc val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get8(s); + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } } } } } + // remove weird white matte from PSD if (channelCount >= 4) { - for (i=0; i < w*h; ++i) { - unsigned char *pixel = out + 4*i; - if (pixel[3] != 0 && pixel[3] != 255) { - // remove weird white matte from PSD - float a = pixel[3] / 255.0f; - float ra = 1.0f / a; - float inv_a = 255.0f * (1 - ra); - pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); - pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); - pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } } } } + // convert to desired output format if (req_comp && req_comp != 4) { - out = stbi__convert_format(out, 4, req_comp, w, h); + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); if (out == NULL) return out; // stbi__convert_format frees input on failure } From 7759a2a93d192951b00804be1466b5e7296ca7c0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 4 Dec 2016 05:25:24 -0800 Subject: [PATCH 406/522] fix "misleading indentation" gcc warning --- stb_image.h | 74 ++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/stb_image.h b/stb_image.h index a2d8219..1e4c23c 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1566,18 +1566,18 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros switch (STBI__COMBO(img_n, req_comp)) { - STBI__CASE(1,2) dest[0]=src[0], dest[1]=255; break; - STBI__CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; - STBI__CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; - STBI__CASE(2,1) dest[0]=src[0]; break; - STBI__CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; - STBI__CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; - STBI__CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; - STBI__CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - STBI__CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; - STBI__CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - STBI__CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; - STBI__CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; default: STBI_ASSERT(0); } #undef STBI__CASE @@ -1615,18 +1615,18 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros switch (STBI__COMBO(img_n, req_comp)) { - STBI__CASE(1,2) dest[0]=src[0], dest[1]=0xffff; break; - STBI__CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; - STBI__CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; break; - STBI__CASE(2,1) dest[0]=src[0]; break; - STBI__CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; - STBI__CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; - STBI__CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; break; - STBI__CASE(3,1) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); break; - STBI__CASE(3,2) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; break; - STBI__CASE(4,1) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); break; - STBI__CASE(4,2) dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; break; - STBI__CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; default: STBI_ASSERT(0); } #undef STBI__CASE @@ -4354,12 +4354,12 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r switch (filter) { // "none" filter turns into a memcpy here; make that explicit. case STBI__F_none: memcpy(cur, raw, nk); break; - STBI__CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; - STBI__CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - STBI__CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; - STBI__CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; - STBI__CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; - STBI__CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; } #undef STBI__CASE raw += nk; @@ -4370,13 +4370,13 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ for (k=0; k < filter_bytes; ++k) switch (filter) { - STBI__CASE(STBI__F_none) cur[k] = raw[k]; break; - STBI__CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break; - STBI__CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - STBI__CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break; - STBI__CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break; - STBI__CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break; - STBI__CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break; + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; } #undef STBI__CASE From 4a1523f60ab0b1a707e147c41dcfc2a421007a8c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 4 Dec 2016 05:28:26 -0800 Subject: [PATCH 407/522] make tga load function static to avoid link errors on multiple instances --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 1e4c23c..6246eb0 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5330,7 +5330,7 @@ errorEnd: } // read 16bit value and convert to 24bit RGB -void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) { stbi__uint16 px = stbi__get16le(s); stbi__uint16 fiveBitMask = 31; From 0b2c06a7e17da43283c872c67f4679b92dcebbb6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 4 Dec 2016 05:39:35 -0800 Subject: [PATCH 408/522] more STB_IMAGE_STATIC fixes --- tests/stb.dsp | 4 ---- tests/test_vorbis.c | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/stb.dsp b/tests/stb.dsp index 7fbb0a8..5b32abb 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -90,10 +90,6 @@ SOURCE=.\grid_reachability.c # End Source File # Begin Source File -SOURCE=..\docs\other_libs.md -# End Source File -# Begin Source File - SOURCE=.\stb.c # End Source File # Begin Source File diff --git a/tests/test_vorbis.c b/tests/test_vorbis.c index d54ed23..341a102 100644 --- a/tests/test_vorbis.c +++ b/tests/test_vorbis.c @@ -1,3 +1,7 @@ +#define STB_IMAGE_STATIC +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + #define STB_VORBIS_HEADER_ONLY #include "stb_vorbis.c" #include "stb.h" From b61b7a74fa050db0679d69ac584312bc0300914c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 4 Dec 2016 05:40:21 -0800 Subject: [PATCH 409/522] update version info --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 71debbf..345e406 100644 --- a/stb_image.h +++ b/stb_image.h @@ -146,7 +146,7 @@ Latest revision history: - 2.13 (2016-11-29) experimental 16-bit API, only for PNG so far + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; From 7fa573cd619cd1e6ddbecf500e6d3009694cc97d Mon Sep 17 00:00:00 2001 From: IntellectualKitty Date: Sun, 4 Dec 2016 16:06:34 -0700 Subject: [PATCH 410/522] Update stb_truetype.h --- stb_truetype.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_truetype.h b/stb_truetype.h index 88a2da1..c3d8e65 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -978,6 +978,7 @@ static int stbtt__isfont(stbtt_uint8 *font) if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts return 0; } From 75a8fd9d41939a4b7712151254d1473f84d39197 Mon Sep 17 00:00:00 2001 From: IntellectualKitty Date: Sun, 4 Dec 2016 17:06:17 -0700 Subject: [PATCH 411/522] Add function to get the number of fonts in a TrueType file --- stb_truetype.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/stb_truetype.h b/stb_truetype.h index 88a2da1..63ccd26 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -95,7 +95,8 @@ // // "Load" a font file from a memory buffer (you have to keep the buffer loaded) // stbtt_InitFont() -// stbtt_GetFontOffsetForIndex() -- use for TTC font collections +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections // // Render a unicode codepoint to a bitmap // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap @@ -629,6 +630,12 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // return '0' for index 0, and -1 for all other indices. You can just skip // this step if you know it's that kind of font. +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. // The following structure is defined publically so you can declare one on // the stack or as a global or etc, but you should treat it as opaque. @@ -1014,6 +1021,22 @@ static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, return -1; } +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return -1; +} + static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) { stbtt_uint32 cmap, t; @@ -3214,6 +3237,11 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); } +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) { return stbtt_InitFont_internal(info, (unsigned char *) data, offset); From a468fbda725c014af5ca2cef3b57ba271d1fb685 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 02:57:06 -0800 Subject: [PATCH 412/522] readme, add rrsprintf.h --- README.md | 4 +- rrsprintf.h | 1055 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1057 insertions(+), 2 deletions(-) create mode 100644 rrsprintf.h diff --git a/README.md b/README.md index 840f061..2b17c3c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ single-file public domain libraries for C/C++ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5399 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.12 | graphics | 6755 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_image.h](stb_image.h)** | 2.13 | graphics | 7099 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.12 | graphics | 3287 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality @@ -28,7 +28,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 19 -Total lines of C code: 47970 +Total lines of C code: 48314 FAQ diff --git a/rrsprintf.h b/rrsprintf.h new file mode 100644 index 0000000..62962e3 --- /dev/null +++ b/rrsprintf.h @@ -0,0 +1,1055 @@ +#ifndef RR_SPRINTF_H_INCLUDE +#define RR_SPRINTF_H_INCLUDE + +/* +Single file sprintf replacement. + +Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. +Hereby placed in public domain. + +This is a full sprintf replacement that supports everything that +the C runtime sprintfs support, including float/double, 64-bit integers, +hex floats, field parameters (%*.*d stuff), length reads backs, etc. + +Why would you need this if sprintf already exists? Well, first off, +it's *much* faster (see below). It's also much smaller than the CRT +versions code-space-wise. We've also added some simple improvements +that are super handy (commas in thousands, callbacks at buffer full, +for example). Finally, the format strings for MSVC and GCC differ +for 64-bit integers (among other small things), so this lets you use +the same format strings in cross platform code. + +It uses the standard single file trick of being both the header file +and the source itself. If you just include it normally, you just get +the header file function definitions. To get the code, you include +it from a C or C++ file and define RR_SPRINTF_IMPLEMENTATION first. + +It only uses va_args macros from the C runtime to do it's work. It +does cast doubles to S64s and shifts and divides U64s, which does +drag in CRT code on most platforms. + +It compiles to roughly 8K with float support, and 4K without. +As a comparison, when using MSVC static libs, calling sprintf drags +in 16K. + +API: +==== +int rrsprintf( char * buf, char const * fmt, ... ) +int rrsnprintf( char * buf, int count, char const * fmt, ... ) + Convert an arg list into a buffer. rrsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int rrvsprintf( char * buf, char const * fmt, va_list va ) +int rrvsnprintf( char * buf, int count, char const * fmt, va_list va ) + Convert a va_list arg list into a buffer. rrvsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int rrvsprintfcb( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) + typedef char * RRSPRINTFCB( char const * buf, void * user, int len ); + Convert into a buffer, calling back every RR_SPRINTF_MIN chars. + Your callback can then copy the chars out, print them or whatever. + This function is actually the workhorse for everything else. + The buffer you pass in must hold at least RR_SPRINTF_MIN characters. + // you return the next buffer to use or 0 to stop converting + +void rrsetseparators( char comma, char period ) + Set the comma and period characters to use. + +FLOATS/DOUBLES: +=============== +This code uses a internal float->ascii conversion method that uses +doubles with error correction (double-doubles, for ~105 bits of +precision). This conversion is round-trip perfect - that is, an atof +of the values output here will give you the bit-exact double back. + +One difference is that our insignificant digits will be different than +with MSVC or GCC (but they don't match each other either). We also +don't attempt to find the minimum length matching float (pre-MSVC15 +doesn't either). + +If you don't need float or doubles at all, define RR_SPRINTF_NOFLOAT +and you'll save 4K of code space. + +64-BIT INTS: +============ +This library also supports 64-bit integers and you can use MSVC style or +GCC style indicators (%I64d or %lld). It supports the C99 specifiers +for size_t and ptr_diff_t (%jd %zd) as well. + +EXTRAS: +======= +Like some GCCs, for integers and floats, you can use a ' (single quote) +specifier and commas will be inserted on the thousands: "%'d" on 12345 +would print 12,345. + +For integers and floats, you can use a "$" specifier and the number +will be converted to float and then divided to get kilo, mega, giga or +tera and then printed, so "%$d" 1024 is "1.0 k", "%$.2d" 2536000 is +"2.42 m", etc. + +In addition to octal and hexadecimal conversions, you can print +integers in binary: "%b" for 256 would print 100. + +PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): +=================================================================== +"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) +"%24d" across all 32-bit ints (4.5x/4.2x faster) +"%x" across all 32-bit ints (4.5x/3.8x faster) +"%08x" across all 32-bit ints (4.3x/3.8x faster) +"%f" across e-10 to e+10 floats (7.3x/6.0x faster) +"%e" across e-10 to e+10 floats (8.1x/6.0x faster) +"%g" across e-10 to e+10 floats (10.0x/7.1x faster) +"%f" for values near e-300 (7.9x/6.5x faster) +"%f" for values near e+300 (10.0x/9.1x faster) +"%e" for values near e-300 (10.1x/7.0x faster) +"%e" for values near e+300 (9.2x/6.0x faster) +"%.320f" for values near e-300 (12.6x/11.2x faster) +"%a" for random values (8.6x/4.3x faster) +"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) +"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) +"%s%s%s" for 64 char strings (7.1x/7.3x faster) +"...512 char string..." ( 35.0x/32.5x faster!) +*/ + +#ifdef RR_SPRINTF_STATIC +#define RRPUBLIC_DEC static +#define RRPUBLIC_DEF static +#else +#ifdef __cplusplus +#define RRPUBLIC_DEC extern "C" +#define RRPUBLIC_DEF extern "C" +#else +#define RRPUBLIC_DEC extern +#define RRPUBLIC_DEF +#endif +#endif + +#include // for va_list() + +#ifndef RR_SPRINTF_MIN +#define RR_SPRINTF_MIN 512 // how many characters per callback +#endif +typedef char * RRSPRINTFCB( char * buf, void * user, int len ); + +#ifndef RR_SPRINTF_DECORATE +#define RR_SPRINTF_DECORATE(name) rr##name // define this before including if you want to change the names +#endif + +#ifndef RR_SPRINTF_IMPLEMENTATION + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ); +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ); +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( sprintf ) ( char * buf, char const * fmt, ... ); +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ); + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ); +RRPUBLIC_DEF void RR_SPRINTF_DECORATE( setseparators )( char comma, char period ); + +#else + +#include // for va_arg() + +#define rU32 unsigned int +#define rS32 signed int + +#ifdef _MSC_VER +#define rU64 unsigned __int64 +#define rS64 signed __int64 +#else +#define rU64 unsigned long long +#define rS64 signed long long +#endif +#define rU16 unsigned short + +#ifndef rUINTa +#if defined(__ppc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) +#define rUINTa rU64 +#else +#define rUINTa rU32 +#endif +#endif + +#ifndef RR_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) +#if defined(_MSC_VER) && (_MSC_VER<1900) +#define RR_SPRINTF_MSVC_MODE +#endif +#endif + +#ifdef RR_SPRINTF_NOUNALIGNED // define this before inclusion to force rrsprint to always use aligned accesses +#define RR_UNALIGNED(code) +#else +#define RR_UNALIGNED(code) code +#endif + +#ifndef RR_SPRINTF_NOFLOAT +// internal float utility functions +static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * decimal_pos, double value, rU32 frac_digits ); +static rS32 rrreal_to_parts( rS64 * bits, rS32 * expo, double value ); +#define RRSPECIAL 0x7000 +#endif + +static char RRperiod='.'; +static char RRcomma=','; +static char rrdiglookup[201]="00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"; + +RRPUBLIC_DEF void RR_SPRINTF_DECORATE( setseparators )( char pcomma, char pperiod ) +{ + RRperiod=pperiod; + RRcomma=pcomma; +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) +{ + static char hex[]="0123456789abcdefxp"; + static char hexu[]="0123456789ABCDEFXP"; + char * bf; + char const * f; + int tlen = 0; + + bf = buf; + f = fmt; + for(;;) + { + rS32 fw,pr,tz; rU32 fl; + + #define LJ 1 + #define LP 2 + #define LS 4 + #define LX 8 + #define LZ 16 + #define BI 32 + #define CS 64 + #define NG 128 + #define KI 256 + #define HW 512 + + // macros for the callback buffer stuff + #define chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=RR_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } + #define chk_cb_buf(bytes) { if ( callback ) { chk_cb_bufL(bytes); } } + #define flush_cb() { chk_cb_bufL(RR_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer + #define cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = RR_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } + + // fast copy everything up to the next % (or end of string) + for(;;) + { + while (((rUINTa)f)&3) + { + schk1: if (f[0]=='%') goto scandd; + schk2: if (f[0]==0) goto endfmt; + chk_cb_buf(1); *bf++=f[0]; ++f; + } + for(;;) + { + rU32 v,c; + v=*(rU32*)f; c=(~v)&0x80808080; + if ((v-0x26262626)&c) goto schk1; + if ((v-0x01010101)&c) goto schk2; + if (callback) if ((RR_SPRINTF_MIN-(int)(bf-buf))<4) goto schk1; + *(rU32*)bf=v; bf+=4; f+=4; + } + } scandd: + + ++f; + + // ok, we have a percent, read the modifiers first + fw = 0; pr = -1; fl = 0; tz = 0; + + // flags + for(;;) + { + switch(f[0]) + { + // if we have left just + case '-': fl|=LJ; ++f; continue; + // if we have leading plus + case '+': fl|=LP; ++f; continue; + // if we have leading space + case ' ': fl|=LS; ++f; continue; + // if we have leading 0x + case '#': fl|=LX; ++f; continue; + // if we have thousand commas + case '\'': fl|=CS; ++f; continue; + // if we have kilo marker + case '$': fl|=KI; ++f; continue; + // if we have leading zero + case '0': fl|=LZ; ++f; goto flags_done; + default: goto flags_done; + } + } + flags_done: + + // get the field width + if ( f[0] == '*' ) {fw = va_arg(va,rU32); ++f;} else { while (( f[0] >= '0' ) && ( f[0] <= '9' )) { fw = fw * 10 + f[0] - '0'; f++; } } + // get the precision + if ( f[0]=='.' ) { ++f; if ( f[0] == '*' ) {pr = va_arg(va,rU32); ++f;} else { pr = 0; while (( f[0] >= '0' ) && ( f[0] <= '9' )) { pr = pr * 10 + f[0] - '0'; f++; } } } + + // handle integer size overrides + switch(f[0]) + { + // are we halfwidth? + case 'h': fl|=HW; ++f; break; + // are we 64-bit (unix style) + case 'l': ++f; if ( f[0]=='l') { fl|=BI; ++f; } break; + // are we 64-bit on intmax? (c99) + case 'j': fl|=BI; ++f; break; + // are we 64-bit on size_t or ptrdiff_t? (c99) + case 'z': case 't': fl|=((sizeof(char*)==8)?BI:0); ++f; break; + // are we 64-bit (msft style) + case 'I': if ( ( f[1]=='6') && ( f[2]=='4') ) { fl|=BI; f+=3; } else if ( ( f[1]=='3') && ( f[2]=='2') ) { f+=3; } else { fl|=((sizeof(void*)==8)?BI:0); ++f; } break; + default: break; + } + + // handle each replacement + switch( f[0] ) + { + #define NUMSZ 512 // big enough for e308 (with commas) or e-307 + char num[NUMSZ]; + char lead[8]; + char tail[8]; + char *s; + char const *h; + rU32 l,n,cs; + rU64 n64; + #ifndef RR_SPRINTF_NOFLOAT + double fv; + #endif + rS32 dp; char const * sn; + + case 's': + // get the string + s = va_arg(va,char*); if (s==0) s = (char*)"null"; + // get the length + sn = s; + for(;;) + { + if ((((rUINTa)sn)&3)==0) break; + lchk: + if (sn[0]==0) goto ld; + ++sn; + } + n = 0xffffffff; + if (pr>=0) { n=(rU32)(sn-s); if (n>=(rU32)pr) goto ld; n=((rU32)(pr-n))>>2; } + while(n) + { + rU32 v=*(rU32*)sn; + if ((v-0x01010101)&(~v)&0x80808080UL) goto lchk; + sn+=4; + --n; + } + goto lchk; + ld: + + l = (rU32) ( sn - s ); + // clamp to precision + if ( l > (rU32)pr ) l = pr; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + // copy the string in + goto scopy; + + case 'c': // char + // get the character + s = num + NUMSZ -1; *s = (char)va_arg(va,int); + l = 1; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + goto scopy; + + case 'n': // weird write-bytes specifier + { int * d = va_arg(va,int*); + *d = tlen + (int)( bf - buf ); } + break; + +#ifdef RR_SPRINTF_NOFLOAT + case 'A': // float + case 'a': // hex float + case 'G': // float + case 'g': // float + case 'E': // float + case 'e': // float + case 'f': // float + va_arg(va,double); // eat it + s = (char*)"No float"; + l = 8; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + goto scopy; +#else + case 'A': // float + h=hexu; + goto hexfloat; + + case 'a': // hex float + h=hex; + hexfloat: + fv = va_arg(va,double); + if (pr==-1) pr=6; // default is 6 + // read the double into a string + if ( rrreal_to_parts( (rS64*)&n64, &dp, fv ) ) + fl |= NG; + + s = num+64; + + // sign + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + + if (dp==-1023) dp=(n64)?-1022:0; else n64|=(((rU64)1)<<52); + n64<<=(64-56); + if (pr<15) n64+=((((rU64)8)<<56)>>(pr*4)); + // add leading chars + + #ifdef RR_SPRINTF_MSVC_MODE + *s++='0';*s++='x'; + #else + lead[1+lead[0]]='0'; lead[2+lead[0]]='x'; lead[0]+=2; + #endif + *s++=h[(n64>>60)&15]; n64<<=4; + if ( pr ) *s++=RRperiod; + sn = s; + + // print the bits + n = pr; if (n>13) n = 13; if (pr>(rS32)n) tz=pr-n; pr = 0; + while(n--) { *s++=h[(n64>>60)&15]; n64<<=4; } + + // print the expo + tail[1]=h[17]; + if (dp<0) { tail[2]='-'; dp=-dp;} else tail[2]='+'; + n = (dp>=1000)?6:((dp>=100)?5:((dp>=10)?4:3)); + tail[0]=(char)n; + for(;;) { tail[n]='0'+dp%10; if (n<=3) break; --n; dp/=10; } + + dp = (int)(s-sn); + l = (int)(s-(num+64)); + s = num+64; + cs = 1 + (3<<24); + goto scopy; + + case 'G': // float + h=hexu; + goto dosmallfloat; + + case 'g': // float + h=hex; + dosmallfloat: + fv = va_arg(va,double); + if (pr==-1) pr=6; else if (pr==0) pr = 1; // default is 6 + // read the double into a string + if ( rrreal_to_str( &sn, &l, num, &dp, fv, (pr-1)|0x80000000 ) ) + fl |= NG; + + // clamp the precision and delete extra zeros after clamp + n = pr; + if ( l > (rU32)pr ) l = pr; while ((l>1)&&(pr)&&(sn[l-1]=='0')) { --pr; --l; } + + // should we use %e + if ((dp<=-4)||(dp>(rS32)n)) + { + if ( pr > (rS32)l ) pr = l-1; else if ( pr ) --pr; // when using %e, there is one digit before the decimal + goto doexpfromg; + } + // this is the insane action to get the pr to match %g sematics for %f + if(dp>0) { pr=(dp<(rS32)l)?l-dp:0; } else { pr = -dp+((pr>(rS32)l)?l:pr); } + goto dofloatfromg; + + case 'E': // float + h=hexu; + goto doexp; + + case 'e': // float + h=hex; + doexp: + fv = va_arg(va,double); + if (pr==-1) pr=6; // default is 6 + // read the double into a string + if ( rrreal_to_str( &sn, &l, num, &dp, fv, pr|0x80000000 ) ) + fl |= NG; + doexpfromg: + tail[0]=0; + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + if ( dp == RRSPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } + s=num+64; + // handle leading chars + *s++=sn[0]; + + if (pr) *s++=RRperiod; + + // handle after decimal + if ((l-1)>(rU32)pr) l=pr+1; + for(n=1;n=100)?5:4; + #endif + tail[0]=(char)n; + for(;;) { tail[n]='0'+dp%10; if (n<=3) break; --n; dp/=10; } + cs = 1 + (3<<24); // how many tens + goto flt_lead; + + case 'f': // float + fv = va_arg(va,double); + doafloat: + // do kilos + if (fl&KI) {while(fl<0x4000000) { if ((fv<1024.0) && (fv>-1024.0)) break; fv/=1024.0; fl+=0x1000000; }} + if (pr==-1) pr=6; // default is 6 + // read the double into a string + if ( rrreal_to_str( &sn, &l, num, &dp, fv, pr ) ) + fl |= NG; + dofloatfromg: + tail[0]=0; + // sign + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + if ( dp == RRSPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } + s=num+64; + + // handle the three decimal varieties + if (dp<=0) + { + rS32 i; + // handle 0.000*000xxxx + *s++='0'; if (pr) *s++=RRperiod; + n=-dp; if((rS32)n>pr) n=pr; i=n; while(i) { if ((((rUINTa)s)&3)==0) break; *s++='0'; --i; } while(i>=4) { *(rU32*)s=0x30303030; s+=4; i-=4; } while(i) { *s++='0'; --i; } + if ((rS32)(l+n)>pr) l=pr-n; i=l; while(i) { *s++=*sn++; --i; } + tz = pr-(n+l); + cs = 1 + (3<<24); // how many tens did we write (for commas below) + } + else + { + cs = (fl&CS)?((600-(rU32)dp)%3):0; + if ((rU32)dp>=l) + { + // handle xxxx000*000.0 + n=0; for(;;) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++=sn[n]; ++n; if (n>=l) break; } } + if (n<(rU32)dp) + { + n = dp - n; + if ((fl&CS)==0) { while(n) { if ((((rUINTa)s)&3)==0) break; *s++='0'; --n; } while(n>=4) { *(rU32*)s=0x30303030; s+=4; n-=4; } } + while(n) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++='0'; --n; } } + } + cs = (int)(s-(num+64)) + (3<<24); // cs is how many tens + if (pr) { *s++=RRperiod; tz=pr;} + } + else + { + // handle xxxxx.xxxx000*000 + n=0; for(;;) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++=sn[n]; ++n; if (n>=(rU32)dp) break; } } + cs = (int)(s-(num+64)) + (3<<24); // cs is how many tens + if (pr) *s++=RRperiod; + if ((l-dp)>(rU32)pr) l=pr+dp; + while(n>24) { tail[2]="_kmgt"[fl>>24]; tail[0]=2; } } }; + + flt_lead: + // get the length that we copied + l = (rU32) ( s-(num+64) ); + s=num+64; + goto scopy; +#endif + + case 'B': // upper binary + h = hexu; + goto binary; + + case 'b': // lower binary + h = hex; + binary: + lead[0]=0; + if (fl&LX) { lead[0]=2;lead[1]='0';lead[2]=h[0xb]; } + l=(8<<4)|(1<<8); + goto radixnum; + + case 'o': // octal + h = hexu; + lead[0]=0; + if (fl&LX) { lead[0]=1;lead[1]='0'; } + l=(3<<4)|(3<<8); + goto radixnum; + + case 'p': // pointer + fl |= (sizeof(void*)==8)?BI:0; + pr = sizeof(void*)*2; + fl &= ~LZ; // 'p' only prints the pointer with zeros + // drop through to X + + case 'X': // upper binary + h = hexu; + goto dohexb; + + case 'x': // lower binary + h = hex; dohexb: + l=(4<<4)|(4<<8); + lead[0]=0; + if (fl&LX) { lead[0]=2;lead[1]='0';lead[2]=h[16]; } + radixnum: + // get the number + if ( fl&BI ) + n64 = va_arg(va,rU64); + else + n64 = va_arg(va,rU32); + + s = num + NUMSZ; dp = 0; + // clear tail, and clear leading if value is zero + tail[0]=0; if (n64==0) { lead[0]=0; if (pr==0) { l=0; cs = ( ((l>>4)&15)) << 24; goto scopy; } } + // convert to string + for(;;) { *--s = h[n64&((1<<(l>>8))-1)]; n64>>=(l>>8); if ( ! ( (n64) || ((rS32) ( (num+NUMSZ) - s ) < pr ) ) ) break; if ( fl&CS) { ++l; if ((l&15)==((l>>4)&15)) { l&=~15; *--s=RRcomma; } } }; + // get the tens and the comma pos + cs = (rU32) ( (num+NUMSZ) - s ) + ( ( ((l>>4)&15)) << 24 ); + // get the length that we copied + l = (rU32) ( (num+NUMSZ) - s ); + // copy it + goto scopy; + + case 'u': // unsigned + case 'i': + case 'd': // integer + // get the integer and abs it + if ( fl&BI ) + { + rS64 i64 = va_arg(va,rS64); n64 = (rU64)i64; if ((f[0]!='u') && (i64<0)) { n64=(rU64)-i64; fl|=NG; } + } + else + { + rS32 i = va_arg(va,rS32); n64 = (rU32)i; if ((f[0]!='u') && (i<0)) { n64=(rU32)-i; fl|=NG; } + } + + #ifndef RR_SPRINTF_NOFLOAT + if (fl&KI) { if (n64<1024) pr=0; else if (pr==-1) pr=1; fv=(double)(rS64)n64; goto doafloat; } + #endif + + // convert to string + s = num+NUMSZ; l=0; + + for(;;) + { + // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) + char * o=s-8; + if (n64>=100000000) { n = (rU32)( n64 % 100000000); n64 /= 100000000; } else {n = (rU32)n64; n64 = 0; } + if((fl&CS)==0) { while(n) { s-=2; *(rU16*)s=*(rU16*)&rrdiglookup[(n%100)*2]; n/=100; } } + while (n) { if ( ( fl&CS) && (l++==3) ) { l=0; *--s=RRcomma; --o; } else { *--s=(char)(n%10)+'0'; n/=10; } } + if (n64==0) { if ((s[0]=='0') && (s!=(num+NUMSZ))) ++s; break; } + while (s!=o) if ( ( fl&CS) && (l++==3) ) { l=0; *--s=RRcomma; --o; } else { *--s='0'; } + } + + tail[0]=0; + // sign + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + + // get the length that we copied + l = (rU32) ( (num+NUMSZ) - s ); if ( l == 0 ) { *--s='0'; l = 1; } + cs = l + (3<<24); + if (pr<0) pr = 0; + + scopy: + // get fw=leading/trailing space, pr=leading zeros + if (pr<(rS32)l) pr = l; + n = pr + lead[0] + tail[0] + tz; + if (fw<(rS32)n) fw = n; + fw -= n; + pr -= l; + + // handle right justify and leading zeros + if ( (fl&LJ)==0 ) + { + if (fl&LZ) // if leading zeros, everything is in pr + { + pr = (fw>pr)?fw:pr; + fw = 0; + } + else + { + fl &= ~CS; // if no leading zeros, then no commas + } + } + + // copy the spaces and/or zeros + if (fw+pr) + { + rS32 i; rU32 c; + + // copy leading spaces (or when doing %8.4d stuff) + if ( (fl&LJ)==0 ) while(fw>0) { cb_buf_clamp(i,fw); fw -= i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(rU32*)bf=0x20202020; bf+=4; i-=4; } while (i) {*bf++=' '; --i;} chk_cb_buf(1); } + + // copy leader + sn=lead+1; while(lead[0]) { cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + + // copy leading zeros + c = cs >> 24; cs &= 0xffffff; + cs = (fl&CS)?((rU32)(c-((pr+cs)%(c+1)))):0; + while(pr>0) { cb_buf_clamp(i,pr); pr -= i; if((fl&CS)==0) { while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(rU32*)bf=0x30303030; bf+=4; i-=4; } } while (i) { if((fl&CS) && (cs++==c)) { cs = 0; *bf++=RRcomma; } else *bf++='0'; --i; } chk_cb_buf(1); } + } + + // copy leader if there is still one + sn=lead+1; while(lead[0]) { rS32 i; cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + + // copy the string + n = l; while (n) { rS32 i; cb_buf_clamp(i,n); n-=i; RR_UNALIGNED( while(i>=4) { *(rU32*)bf=*(rU32*)s; bf+=4; s+=4; i-=4; } ) while (i) {*bf++=*s++; --i;} chk_cb_buf(1); } + + // copy trailing zeros + while(tz) { rS32 i; cb_buf_clamp(i,tz); tz -= i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(rU32*)bf=0x30303030; bf+=4; i-=4; } while (i) {*bf++='0'; --i;} chk_cb_buf(1); } + + // copy tail if there is one + sn=tail+1; while(tail[0]) { rS32 i; cb_buf_clamp(i,tail[0]); tail[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + + // handle the left justify + if (fl&LJ) if (fw>0) { while (fw) { rS32 i; cb_buf_clamp(i,fw); fw-=i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(rU32*)bf=0x20202020; bf+=4; i-=4; } while (i--) *bf++=' '; chk_cb_buf(1); } } + break; + + default: // unknown, just copy code + s = num + NUMSZ -1; *s = f[0]; + l = 1; + fw=pr=fl=0; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + goto scopy; + } + ++f; + } + endfmt: + + if (!callback) + *bf = 0; + else + flush_cb(); + + done: + return tlen + (int)(bf-buf); +} + +// cleanup +#undef LJ +#undef LP +#undef LS +#undef LX +#undef LZ +#undef BI +#undef CS +#undef NG +#undef KI +#undef NUMSZ +#undef chk_cb_bufL +#undef chk_cb_buf +#undef flush_cb +#undef cb_buf_clamp + +// ============================================================================ +// wrapper functions + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( sprintf )( char * buf, char const * fmt, ... ) +{ + va_list va; + va_start( va, fmt ); + return RR_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); +} + +typedef struct RRCCS +{ + char * buf; + int count; + char tmp[ RR_SPRINTF_MIN ]; +} RRCCS; + +static char * rrclampcallback( char * buf, void * user, int len ) +{ + RRCCS * c = (RRCCS*)user; + + if ( len > c->count ) len = c->count; + + if (len) + { + if ( buf != c->buf ) + { + char * s, * d, * se; + d = c->buf; s = buf; se = buf+len; + do{ *d++ = *s++; } while (sbuf += len; + c->count -= len; + } + + if ( c->count <= 0 ) return 0; + return ( c->count >= RR_SPRINTF_MIN ) ? c->buf : c->tmp; // go direct into buffer if you can +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) +{ + RRCCS c; + int l; + + if ( count == 0 ) + return 0; + + c.buf = buf; + c.count = count; + + RR_SPRINTF_DECORATE( vsprintfcb )( rrclampcallback, &c, rrclampcallback(0,&c,0), fmt, va ); + + // zero-terminate + l = (int)( c.buf - buf ); + if ( l >= count ) // should never be greater, only equal (or less) than count + l = count - 1; + buf[l] = 0; + + return l; +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ) +{ + va_list va; + va_start( va, fmt ); + + return RR_SPRINTF_DECORATE( vsnprintf )( buf, count, fmt, va ); +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ) +{ + return RR_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); +} + +// ======================================================================= +// low level float utility functions + +#ifndef RR_SPRINTF_NOFLOAT + + // copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) + #define RRCOPYFP(dest,src) { int cn; for(cn=0;cn<8;cn++) ((char*)&dest)[cn]=((char*)&src)[cn]; } + +// get float info +static rS32 rrreal_to_parts( rS64 * bits, rS32 * expo, double value ) +{ + double d; + rS64 b = 0; + + // load value and round at the frac_digits + d = value; + + RRCOPYFP( b, d ); + + *bits = b & ((((rU64)1)<<52)-1); + *expo = ((b >> 52) & 2047)-1023; + + return (rS32)(b >> 63); +} + +static double const rrbot[23]={1e+000,1e+001,1e+002,1e+003,1e+004,1e+005,1e+006,1e+007,1e+008,1e+009,1e+010,1e+011,1e+012,1e+013,1e+014,1e+015,1e+016,1e+017,1e+018,1e+019,1e+020,1e+021,1e+022}; +static double const rrnegbot[22]={1e-001,1e-002,1e-003,1e-004,1e-005,1e-006,1e-007,1e-008,1e-009,1e-010,1e-011,1e-012,1e-013,1e-014,1e-015,1e-016,1e-017,1e-018,1e-019,1e-020,1e-021,1e-022}; +static double const rrnegboterr[22]={-5.551115123125783e-018,-2.0816681711721684e-019,-2.0816681711721686e-020,-4.7921736023859299e-021,-8.1803053914031305e-022,4.5251888174113741e-023,4.5251888174113739e-024,-2.0922560830128471e-025,-6.2281591457779853e-026,-3.6432197315497743e-027,6.0503030718060191e-028,2.0113352370744385e-029,-3.0373745563400371e-030,1.1806906454401013e-032,-7.7705399876661076e-032,2.0902213275965398e-033,-7.1542424054621921e-034,-7.1542424054621926e-035,2.4754073164739869e-036,5.4846728545790429e-037,9.2462547772103625e-038,-4.8596774326570872e-039}; +static double const rrtop[13]={1e+023,1e+046,1e+069,1e+092,1e+115,1e+138,1e+161,1e+184,1e+207,1e+230,1e+253,1e+276,1e+299}; +static double const rrnegtop[13]={1e-023,1e-046,1e-069,1e-092,1e-115,1e-138,1e-161,1e-184,1e-207,1e-230,1e-253,1e-276,1e-299}; +static double const rrtoperr[13]={8388608,6.8601809640529717e+028,-7.253143638152921e+052,-4.3377296974619174e+075,-1.5559416129466825e+098,-3.2841562489204913e+121,-3.7745893248228135e+144,-1.7356668416969134e+167,-3.8893577551088374e+190,-9.9566444326005119e+213,6.3641293062232429e+236,-5.2069140800249813e+259,-5.2504760255204387e+282}; +static double const rrnegtoperr[13]={3.9565301985100693e-040,-2.299904345391321e-063,3.6506201437945798e-086,1.1875228833981544e-109,-5.0644902316928607e-132,-6.7156837247865426e-155,-2.812077463003139e-178,-5.7778912386589953e-201,7.4997100559334532e-224,-4.6439668915134491e-247,-6.3691100762962136e-270,-9.436808465446358e-293,8.0970921678014997e-317}; + +#if defined(_MSC_VER) && (_MSC_VER<=1200) +static rU64 const rrpot[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000,100000000000, 1000000000000,10000000000000,100000000000000,1000000000000000, 10000000000000000,100000000000000000,1000000000000000000,10000000000000000000U }; +#define rrtento19th ((rU64)1000000000000000000) +#else +static rU64 const rrpot[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000ULL,100000000000ULL, 1000000000000ULL,10000000000000ULL,100000000000000ULL,1000000000000000ULL, 10000000000000000ULL,100000000000000000ULL,1000000000000000000ULL,10000000000000000000ULL }; +#define rrtento19th (1000000000000000000ULL) +#endif + +#define rrddmulthi(oh,ol,xh,yh) \ +{ \ + double ahi=0,alo,bhi=0,blo; \ + rS64 bt; \ + oh = xh * yh; \ + RRCOPYFP(bt,xh); bt&=((~(rU64)0)<<27); RRCOPYFP(ahi,bt); alo = xh-ahi; \ + RRCOPYFP(bt,yh); bt&=((~(rU64)0)<<27); RRCOPYFP(bhi,bt); blo = yh-bhi; \ + ol = ((ahi*bhi-oh)+ahi*blo+alo*bhi)+alo*blo; \ +} + +#define rrddtoS64(ob,xh,xl) \ +{ \ + double ahi=0,alo,vh,t;\ + ob = (rS64)ph;\ + vh=(double)ob;\ + ahi = ( xh - vh );\ + t = ( ahi - xh );\ + alo = (xh-(ahi-t))-(vh+t);\ + ob += (rS64)(ahi+alo+xl);\ +} + + +#define rrddrenorm(oh,ol) { double s; s=oh+ol; ol=ol-(s-oh); oh=s; } + +#define rrddmultlo(oh,ol,xh,xl,yh,yl) \ + ol = ol + ( xh*yl + xl*yh ); \ + +#define rrddmultlos(oh,ol,xh,yl) \ + ol = ol + ( xh*yl ); \ + +static void rrraise_to_power10( double *ohi, double *olo, double d, rS32 power ) // power can be -323 to +350 +{ + double ph, pl; + if ((power>=0) && (power<=22)) + { + rrddmulthi(ph,pl,d,rrbot[power]); + } + else + { + rS32 e,et,eb; + double p2h,p2l; + + e=power; if (power<0) e=-e; + et = (e*0x2c9)>>14;/* %23 */ if (et>13) et=13; eb = e-(et*23); + + ph = d; pl = 0.0; + if (power<0) + { + if (eb) { --eb; rrddmulthi(ph,pl,d,rrnegbot[eb]); rrddmultlos(ph,pl,d,rrnegboterr[eb]); } + if (et) + { + rrddrenorm(ph,pl); + --et; rrddmulthi(p2h,p2l,ph,rrnegtop[et]); rrddmultlo(p2h,p2l,ph,pl,rrnegtop[et],rrnegtoperr[et]); ph=p2h;pl=p2l; + } + } + else + { + if (eb) + { + e = eb; if (eb>22) eb=22; e -= eb; + rrddmulthi(ph,pl,d,rrbot[eb]); + if ( e ) { rrddrenorm(ph,pl); rrddmulthi(p2h,p2l,ph,rrbot[e]); rrddmultlos(p2h,p2l,rrbot[e],pl); ph=p2h;pl=p2l; } + } + if (et) + { + rrddrenorm(ph,pl); + --et; rrddmulthi(p2h,p2l,ph,rrtop[et]); rrddmultlo(p2h,p2l,ph,pl,rrtop[et],rrtoperr[et]); ph=p2h;pl=p2l; + } + } + } + rrddrenorm(ph,pl); + *ohi = ph; *olo = pl; +} + +// given a float value, returns the significant bits in bits, and the position of the +// decimal point in decimal_pos. +/-INF and NAN are specified by special values +// returned in the decimal_pos parameter. +// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 +static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * decimal_pos, double value, rU32 frac_digits ) +{ + double d; + rS64 bits = 0; + rS32 expo, e, ng, tens; + + d = value; + RRCOPYFP(bits,d); + expo = (bits >> 52) & 2047; + ng = (rS32)(bits >> 63); + if (ng) d=-d; + + if ( expo == 2047 ) // is nan or inf? + { + *start = (bits&((((rU64)1)<<52)-1)) ? "NaN" : "Inf"; + *decimal_pos = RRSPECIAL; + *len = 3; + return ng; + } + + if ( expo == 0 ) // is zero or denormal + { + if ((bits<<1)==0) // do zero + { + *decimal_pos = 1; + *start = out; + out[0] = '0'; *len = 1; + return ng; + } + // find the right expo for denormals + { + rS64 v = ((rU64)1)<<51; + while ((bits&v)==0) { --expo; v >>= 1; } + } + } + + // find the decimal exponent as well as the decimal bits of the value + { + double ph,pl; + + // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 + tens=expo-1023; tens = (tens<0)?((tens*617)/2048):(((tens*1233)/4096)+1); + + // move the significant bits into position and stick them into an int + rrraise_to_power10( &ph, &pl, d, 18-tens ); + + // get full as much precision from double-double as possible + rrddtoS64( bits, ph,pl ); + + // check if we undershot + if ( ((rU64)bits) >= rrtento19th ) ++tens; + } + + // now do the rounding in integer land + frac_digits = ( frac_digits & 0x80000000 ) ? ( (frac_digits&0x7ffffff) + 1 ) : ( tens + frac_digits ); + if ( ( frac_digits < 24 ) ) + { + rU32 dg = 1; if ((rU64)bits >= rrpot[9] ) dg=10; while( (rU64)bits >= rrpot[dg] ) { ++dg; if (dg==20) goto noround; } + if ( frac_digits < dg ) + { + rU64 r; + // add 0.5 at the right position and round + e = dg - frac_digits; + if ( (rU32)e >= 24 ) goto noround; + r = rrpot[e]; + bits = bits + (r/2); + if ( (rU64)bits >= rrpot[dg] ) ++tens; + bits /= r; + } + noround:; + } + + // kill long trailing runs of zeros + if ( bits ) + { + rU32 n; for(;;) { if ( bits<=0xffffffff ) break; if (bits%1000) goto donez; bits/=1000; } n = (rU32)bits; while ((n%1000)==0) n/=1000; bits=n; donez:; + } + + // convert to string + out += 64; + e = 0; + for(;;) + { + rU32 n; + char * o = out-8; + // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) + if (bits>=100000000) { n = (rU32)( bits % 100000000); bits /= 100000000; } else {n = (rU32)bits; bits = 0; } + while(n) { out-=2; *(rU16*)out=*(rU16*)&rrdiglookup[(n%100)*2]; n/=100; e+=2; } + if (bits==0) { if ((e) && (out[0]=='0')) { ++out; --e; } break; } + while( out!=o ) { *--out ='0'; ++e; } + } + + *decimal_pos = tens; + *start = out; + *len = e; + return ng; +} + +#undef rrddmulthi +#undef rrddrenorm +#undef rrddmultlo +#undef rrddmultlos +#undef RRSPECIAL +#undef RRCOPYFP + +#endif + +// clean up +#undef rU16 +#undef rU32 +#undef rS32 +#undef rU64 +#undef rS64 +#undef RRPUBLIC_DEC +#undef RRPUBLIC_DEF +#undef RR_SPRINTF_DECORATE +#undef RR_UNALIGNED + +#endif + +#endif From 454ed822a7a3c278cfc63bd0168bc54d1015b120 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 02:57:49 -0800 Subject: [PATCH 413/522] deprecate rrsprintf --- deprecated/rrsprintf.h | 1055 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1055 insertions(+) create mode 100644 deprecated/rrsprintf.h diff --git a/deprecated/rrsprintf.h b/deprecated/rrsprintf.h new file mode 100644 index 0000000..62962e3 --- /dev/null +++ b/deprecated/rrsprintf.h @@ -0,0 +1,1055 @@ +#ifndef RR_SPRINTF_H_INCLUDE +#define RR_SPRINTF_H_INCLUDE + +/* +Single file sprintf replacement. + +Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. +Hereby placed in public domain. + +This is a full sprintf replacement that supports everything that +the C runtime sprintfs support, including float/double, 64-bit integers, +hex floats, field parameters (%*.*d stuff), length reads backs, etc. + +Why would you need this if sprintf already exists? Well, first off, +it's *much* faster (see below). It's also much smaller than the CRT +versions code-space-wise. We've also added some simple improvements +that are super handy (commas in thousands, callbacks at buffer full, +for example). Finally, the format strings for MSVC and GCC differ +for 64-bit integers (among other small things), so this lets you use +the same format strings in cross platform code. + +It uses the standard single file trick of being both the header file +and the source itself. If you just include it normally, you just get +the header file function definitions. To get the code, you include +it from a C or C++ file and define RR_SPRINTF_IMPLEMENTATION first. + +It only uses va_args macros from the C runtime to do it's work. It +does cast doubles to S64s and shifts and divides U64s, which does +drag in CRT code on most platforms. + +It compiles to roughly 8K with float support, and 4K without. +As a comparison, when using MSVC static libs, calling sprintf drags +in 16K. + +API: +==== +int rrsprintf( char * buf, char const * fmt, ... ) +int rrsnprintf( char * buf, int count, char const * fmt, ... ) + Convert an arg list into a buffer. rrsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int rrvsprintf( char * buf, char const * fmt, va_list va ) +int rrvsnprintf( char * buf, int count, char const * fmt, va_list va ) + Convert a va_list arg list into a buffer. rrvsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int rrvsprintfcb( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) + typedef char * RRSPRINTFCB( char const * buf, void * user, int len ); + Convert into a buffer, calling back every RR_SPRINTF_MIN chars. + Your callback can then copy the chars out, print them or whatever. + This function is actually the workhorse for everything else. + The buffer you pass in must hold at least RR_SPRINTF_MIN characters. + // you return the next buffer to use or 0 to stop converting + +void rrsetseparators( char comma, char period ) + Set the comma and period characters to use. + +FLOATS/DOUBLES: +=============== +This code uses a internal float->ascii conversion method that uses +doubles with error correction (double-doubles, for ~105 bits of +precision). This conversion is round-trip perfect - that is, an atof +of the values output here will give you the bit-exact double back. + +One difference is that our insignificant digits will be different than +with MSVC or GCC (but they don't match each other either). We also +don't attempt to find the minimum length matching float (pre-MSVC15 +doesn't either). + +If you don't need float or doubles at all, define RR_SPRINTF_NOFLOAT +and you'll save 4K of code space. + +64-BIT INTS: +============ +This library also supports 64-bit integers and you can use MSVC style or +GCC style indicators (%I64d or %lld). It supports the C99 specifiers +for size_t and ptr_diff_t (%jd %zd) as well. + +EXTRAS: +======= +Like some GCCs, for integers and floats, you can use a ' (single quote) +specifier and commas will be inserted on the thousands: "%'d" on 12345 +would print 12,345. + +For integers and floats, you can use a "$" specifier and the number +will be converted to float and then divided to get kilo, mega, giga or +tera and then printed, so "%$d" 1024 is "1.0 k", "%$.2d" 2536000 is +"2.42 m", etc. + +In addition to octal and hexadecimal conversions, you can print +integers in binary: "%b" for 256 would print 100. + +PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): +=================================================================== +"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) +"%24d" across all 32-bit ints (4.5x/4.2x faster) +"%x" across all 32-bit ints (4.5x/3.8x faster) +"%08x" across all 32-bit ints (4.3x/3.8x faster) +"%f" across e-10 to e+10 floats (7.3x/6.0x faster) +"%e" across e-10 to e+10 floats (8.1x/6.0x faster) +"%g" across e-10 to e+10 floats (10.0x/7.1x faster) +"%f" for values near e-300 (7.9x/6.5x faster) +"%f" for values near e+300 (10.0x/9.1x faster) +"%e" for values near e-300 (10.1x/7.0x faster) +"%e" for values near e+300 (9.2x/6.0x faster) +"%.320f" for values near e-300 (12.6x/11.2x faster) +"%a" for random values (8.6x/4.3x faster) +"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) +"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) +"%s%s%s" for 64 char strings (7.1x/7.3x faster) +"...512 char string..." ( 35.0x/32.5x faster!) +*/ + +#ifdef RR_SPRINTF_STATIC +#define RRPUBLIC_DEC static +#define RRPUBLIC_DEF static +#else +#ifdef __cplusplus +#define RRPUBLIC_DEC extern "C" +#define RRPUBLIC_DEF extern "C" +#else +#define RRPUBLIC_DEC extern +#define RRPUBLIC_DEF +#endif +#endif + +#include // for va_list() + +#ifndef RR_SPRINTF_MIN +#define RR_SPRINTF_MIN 512 // how many characters per callback +#endif +typedef char * RRSPRINTFCB( char * buf, void * user, int len ); + +#ifndef RR_SPRINTF_DECORATE +#define RR_SPRINTF_DECORATE(name) rr##name // define this before including if you want to change the names +#endif + +#ifndef RR_SPRINTF_IMPLEMENTATION + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ); +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ); +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( sprintf ) ( char * buf, char const * fmt, ... ); +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ); + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ); +RRPUBLIC_DEF void RR_SPRINTF_DECORATE( setseparators )( char comma, char period ); + +#else + +#include // for va_arg() + +#define rU32 unsigned int +#define rS32 signed int + +#ifdef _MSC_VER +#define rU64 unsigned __int64 +#define rS64 signed __int64 +#else +#define rU64 unsigned long long +#define rS64 signed long long +#endif +#define rU16 unsigned short + +#ifndef rUINTa +#if defined(__ppc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) +#define rUINTa rU64 +#else +#define rUINTa rU32 +#endif +#endif + +#ifndef RR_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) +#if defined(_MSC_VER) && (_MSC_VER<1900) +#define RR_SPRINTF_MSVC_MODE +#endif +#endif + +#ifdef RR_SPRINTF_NOUNALIGNED // define this before inclusion to force rrsprint to always use aligned accesses +#define RR_UNALIGNED(code) +#else +#define RR_UNALIGNED(code) code +#endif + +#ifndef RR_SPRINTF_NOFLOAT +// internal float utility functions +static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * decimal_pos, double value, rU32 frac_digits ); +static rS32 rrreal_to_parts( rS64 * bits, rS32 * expo, double value ); +#define RRSPECIAL 0x7000 +#endif + +static char RRperiod='.'; +static char RRcomma=','; +static char rrdiglookup[201]="00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"; + +RRPUBLIC_DEF void RR_SPRINTF_DECORATE( setseparators )( char pcomma, char pperiod ) +{ + RRperiod=pperiod; + RRcomma=pcomma; +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) +{ + static char hex[]="0123456789abcdefxp"; + static char hexu[]="0123456789ABCDEFXP"; + char * bf; + char const * f; + int tlen = 0; + + bf = buf; + f = fmt; + for(;;) + { + rS32 fw,pr,tz; rU32 fl; + + #define LJ 1 + #define LP 2 + #define LS 4 + #define LX 8 + #define LZ 16 + #define BI 32 + #define CS 64 + #define NG 128 + #define KI 256 + #define HW 512 + + // macros for the callback buffer stuff + #define chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=RR_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } + #define chk_cb_buf(bytes) { if ( callback ) { chk_cb_bufL(bytes); } } + #define flush_cb() { chk_cb_bufL(RR_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer + #define cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = RR_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } + + // fast copy everything up to the next % (or end of string) + for(;;) + { + while (((rUINTa)f)&3) + { + schk1: if (f[0]=='%') goto scandd; + schk2: if (f[0]==0) goto endfmt; + chk_cb_buf(1); *bf++=f[0]; ++f; + } + for(;;) + { + rU32 v,c; + v=*(rU32*)f; c=(~v)&0x80808080; + if ((v-0x26262626)&c) goto schk1; + if ((v-0x01010101)&c) goto schk2; + if (callback) if ((RR_SPRINTF_MIN-(int)(bf-buf))<4) goto schk1; + *(rU32*)bf=v; bf+=4; f+=4; + } + } scandd: + + ++f; + + // ok, we have a percent, read the modifiers first + fw = 0; pr = -1; fl = 0; tz = 0; + + // flags + for(;;) + { + switch(f[0]) + { + // if we have left just + case '-': fl|=LJ; ++f; continue; + // if we have leading plus + case '+': fl|=LP; ++f; continue; + // if we have leading space + case ' ': fl|=LS; ++f; continue; + // if we have leading 0x + case '#': fl|=LX; ++f; continue; + // if we have thousand commas + case '\'': fl|=CS; ++f; continue; + // if we have kilo marker + case '$': fl|=KI; ++f; continue; + // if we have leading zero + case '0': fl|=LZ; ++f; goto flags_done; + default: goto flags_done; + } + } + flags_done: + + // get the field width + if ( f[0] == '*' ) {fw = va_arg(va,rU32); ++f;} else { while (( f[0] >= '0' ) && ( f[0] <= '9' )) { fw = fw * 10 + f[0] - '0'; f++; } } + // get the precision + if ( f[0]=='.' ) { ++f; if ( f[0] == '*' ) {pr = va_arg(va,rU32); ++f;} else { pr = 0; while (( f[0] >= '0' ) && ( f[0] <= '9' )) { pr = pr * 10 + f[0] - '0'; f++; } } } + + // handle integer size overrides + switch(f[0]) + { + // are we halfwidth? + case 'h': fl|=HW; ++f; break; + // are we 64-bit (unix style) + case 'l': ++f; if ( f[0]=='l') { fl|=BI; ++f; } break; + // are we 64-bit on intmax? (c99) + case 'j': fl|=BI; ++f; break; + // are we 64-bit on size_t or ptrdiff_t? (c99) + case 'z': case 't': fl|=((sizeof(char*)==8)?BI:0); ++f; break; + // are we 64-bit (msft style) + case 'I': if ( ( f[1]=='6') && ( f[2]=='4') ) { fl|=BI; f+=3; } else if ( ( f[1]=='3') && ( f[2]=='2') ) { f+=3; } else { fl|=((sizeof(void*)==8)?BI:0); ++f; } break; + default: break; + } + + // handle each replacement + switch( f[0] ) + { + #define NUMSZ 512 // big enough for e308 (with commas) or e-307 + char num[NUMSZ]; + char lead[8]; + char tail[8]; + char *s; + char const *h; + rU32 l,n,cs; + rU64 n64; + #ifndef RR_SPRINTF_NOFLOAT + double fv; + #endif + rS32 dp; char const * sn; + + case 's': + // get the string + s = va_arg(va,char*); if (s==0) s = (char*)"null"; + // get the length + sn = s; + for(;;) + { + if ((((rUINTa)sn)&3)==0) break; + lchk: + if (sn[0]==0) goto ld; + ++sn; + } + n = 0xffffffff; + if (pr>=0) { n=(rU32)(sn-s); if (n>=(rU32)pr) goto ld; n=((rU32)(pr-n))>>2; } + while(n) + { + rU32 v=*(rU32*)sn; + if ((v-0x01010101)&(~v)&0x80808080UL) goto lchk; + sn+=4; + --n; + } + goto lchk; + ld: + + l = (rU32) ( sn - s ); + // clamp to precision + if ( l > (rU32)pr ) l = pr; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + // copy the string in + goto scopy; + + case 'c': // char + // get the character + s = num + NUMSZ -1; *s = (char)va_arg(va,int); + l = 1; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + goto scopy; + + case 'n': // weird write-bytes specifier + { int * d = va_arg(va,int*); + *d = tlen + (int)( bf - buf ); } + break; + +#ifdef RR_SPRINTF_NOFLOAT + case 'A': // float + case 'a': // hex float + case 'G': // float + case 'g': // float + case 'E': // float + case 'e': // float + case 'f': // float + va_arg(va,double); // eat it + s = (char*)"No float"; + l = 8; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + goto scopy; +#else + case 'A': // float + h=hexu; + goto hexfloat; + + case 'a': // hex float + h=hex; + hexfloat: + fv = va_arg(va,double); + if (pr==-1) pr=6; // default is 6 + // read the double into a string + if ( rrreal_to_parts( (rS64*)&n64, &dp, fv ) ) + fl |= NG; + + s = num+64; + + // sign + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + + if (dp==-1023) dp=(n64)?-1022:0; else n64|=(((rU64)1)<<52); + n64<<=(64-56); + if (pr<15) n64+=((((rU64)8)<<56)>>(pr*4)); + // add leading chars + + #ifdef RR_SPRINTF_MSVC_MODE + *s++='0';*s++='x'; + #else + lead[1+lead[0]]='0'; lead[2+lead[0]]='x'; lead[0]+=2; + #endif + *s++=h[(n64>>60)&15]; n64<<=4; + if ( pr ) *s++=RRperiod; + sn = s; + + // print the bits + n = pr; if (n>13) n = 13; if (pr>(rS32)n) tz=pr-n; pr = 0; + while(n--) { *s++=h[(n64>>60)&15]; n64<<=4; } + + // print the expo + tail[1]=h[17]; + if (dp<0) { tail[2]='-'; dp=-dp;} else tail[2]='+'; + n = (dp>=1000)?6:((dp>=100)?5:((dp>=10)?4:3)); + tail[0]=(char)n; + for(;;) { tail[n]='0'+dp%10; if (n<=3) break; --n; dp/=10; } + + dp = (int)(s-sn); + l = (int)(s-(num+64)); + s = num+64; + cs = 1 + (3<<24); + goto scopy; + + case 'G': // float + h=hexu; + goto dosmallfloat; + + case 'g': // float + h=hex; + dosmallfloat: + fv = va_arg(va,double); + if (pr==-1) pr=6; else if (pr==0) pr = 1; // default is 6 + // read the double into a string + if ( rrreal_to_str( &sn, &l, num, &dp, fv, (pr-1)|0x80000000 ) ) + fl |= NG; + + // clamp the precision and delete extra zeros after clamp + n = pr; + if ( l > (rU32)pr ) l = pr; while ((l>1)&&(pr)&&(sn[l-1]=='0')) { --pr; --l; } + + // should we use %e + if ((dp<=-4)||(dp>(rS32)n)) + { + if ( pr > (rS32)l ) pr = l-1; else if ( pr ) --pr; // when using %e, there is one digit before the decimal + goto doexpfromg; + } + // this is the insane action to get the pr to match %g sematics for %f + if(dp>0) { pr=(dp<(rS32)l)?l-dp:0; } else { pr = -dp+((pr>(rS32)l)?l:pr); } + goto dofloatfromg; + + case 'E': // float + h=hexu; + goto doexp; + + case 'e': // float + h=hex; + doexp: + fv = va_arg(va,double); + if (pr==-1) pr=6; // default is 6 + // read the double into a string + if ( rrreal_to_str( &sn, &l, num, &dp, fv, pr|0x80000000 ) ) + fl |= NG; + doexpfromg: + tail[0]=0; + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + if ( dp == RRSPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } + s=num+64; + // handle leading chars + *s++=sn[0]; + + if (pr) *s++=RRperiod; + + // handle after decimal + if ((l-1)>(rU32)pr) l=pr+1; + for(n=1;n=100)?5:4; + #endif + tail[0]=(char)n; + for(;;) { tail[n]='0'+dp%10; if (n<=3) break; --n; dp/=10; } + cs = 1 + (3<<24); // how many tens + goto flt_lead; + + case 'f': // float + fv = va_arg(va,double); + doafloat: + // do kilos + if (fl&KI) {while(fl<0x4000000) { if ((fv<1024.0) && (fv>-1024.0)) break; fv/=1024.0; fl+=0x1000000; }} + if (pr==-1) pr=6; // default is 6 + // read the double into a string + if ( rrreal_to_str( &sn, &l, num, &dp, fv, pr ) ) + fl |= NG; + dofloatfromg: + tail[0]=0; + // sign + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + if ( dp == RRSPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } + s=num+64; + + // handle the three decimal varieties + if (dp<=0) + { + rS32 i; + // handle 0.000*000xxxx + *s++='0'; if (pr) *s++=RRperiod; + n=-dp; if((rS32)n>pr) n=pr; i=n; while(i) { if ((((rUINTa)s)&3)==0) break; *s++='0'; --i; } while(i>=4) { *(rU32*)s=0x30303030; s+=4; i-=4; } while(i) { *s++='0'; --i; } + if ((rS32)(l+n)>pr) l=pr-n; i=l; while(i) { *s++=*sn++; --i; } + tz = pr-(n+l); + cs = 1 + (3<<24); // how many tens did we write (for commas below) + } + else + { + cs = (fl&CS)?((600-(rU32)dp)%3):0; + if ((rU32)dp>=l) + { + // handle xxxx000*000.0 + n=0; for(;;) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++=sn[n]; ++n; if (n>=l) break; } } + if (n<(rU32)dp) + { + n = dp - n; + if ((fl&CS)==0) { while(n) { if ((((rUINTa)s)&3)==0) break; *s++='0'; --n; } while(n>=4) { *(rU32*)s=0x30303030; s+=4; n-=4; } } + while(n) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++='0'; --n; } } + } + cs = (int)(s-(num+64)) + (3<<24); // cs is how many tens + if (pr) { *s++=RRperiod; tz=pr;} + } + else + { + // handle xxxxx.xxxx000*000 + n=0; for(;;) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++=sn[n]; ++n; if (n>=(rU32)dp) break; } } + cs = (int)(s-(num+64)) + (3<<24); // cs is how many tens + if (pr) *s++=RRperiod; + if ((l-dp)>(rU32)pr) l=pr+dp; + while(n>24) { tail[2]="_kmgt"[fl>>24]; tail[0]=2; } } }; + + flt_lead: + // get the length that we copied + l = (rU32) ( s-(num+64) ); + s=num+64; + goto scopy; +#endif + + case 'B': // upper binary + h = hexu; + goto binary; + + case 'b': // lower binary + h = hex; + binary: + lead[0]=0; + if (fl&LX) { lead[0]=2;lead[1]='0';lead[2]=h[0xb]; } + l=(8<<4)|(1<<8); + goto radixnum; + + case 'o': // octal + h = hexu; + lead[0]=0; + if (fl&LX) { lead[0]=1;lead[1]='0'; } + l=(3<<4)|(3<<8); + goto radixnum; + + case 'p': // pointer + fl |= (sizeof(void*)==8)?BI:0; + pr = sizeof(void*)*2; + fl &= ~LZ; // 'p' only prints the pointer with zeros + // drop through to X + + case 'X': // upper binary + h = hexu; + goto dohexb; + + case 'x': // lower binary + h = hex; dohexb: + l=(4<<4)|(4<<8); + lead[0]=0; + if (fl&LX) { lead[0]=2;lead[1]='0';lead[2]=h[16]; } + radixnum: + // get the number + if ( fl&BI ) + n64 = va_arg(va,rU64); + else + n64 = va_arg(va,rU32); + + s = num + NUMSZ; dp = 0; + // clear tail, and clear leading if value is zero + tail[0]=0; if (n64==0) { lead[0]=0; if (pr==0) { l=0; cs = ( ((l>>4)&15)) << 24; goto scopy; } } + // convert to string + for(;;) { *--s = h[n64&((1<<(l>>8))-1)]; n64>>=(l>>8); if ( ! ( (n64) || ((rS32) ( (num+NUMSZ) - s ) < pr ) ) ) break; if ( fl&CS) { ++l; if ((l&15)==((l>>4)&15)) { l&=~15; *--s=RRcomma; } } }; + // get the tens and the comma pos + cs = (rU32) ( (num+NUMSZ) - s ) + ( ( ((l>>4)&15)) << 24 ); + // get the length that we copied + l = (rU32) ( (num+NUMSZ) - s ); + // copy it + goto scopy; + + case 'u': // unsigned + case 'i': + case 'd': // integer + // get the integer and abs it + if ( fl&BI ) + { + rS64 i64 = va_arg(va,rS64); n64 = (rU64)i64; if ((f[0]!='u') && (i64<0)) { n64=(rU64)-i64; fl|=NG; } + } + else + { + rS32 i = va_arg(va,rS32); n64 = (rU32)i; if ((f[0]!='u') && (i<0)) { n64=(rU32)-i; fl|=NG; } + } + + #ifndef RR_SPRINTF_NOFLOAT + if (fl&KI) { if (n64<1024) pr=0; else if (pr==-1) pr=1; fv=(double)(rS64)n64; goto doafloat; } + #endif + + // convert to string + s = num+NUMSZ; l=0; + + for(;;) + { + // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) + char * o=s-8; + if (n64>=100000000) { n = (rU32)( n64 % 100000000); n64 /= 100000000; } else {n = (rU32)n64; n64 = 0; } + if((fl&CS)==0) { while(n) { s-=2; *(rU16*)s=*(rU16*)&rrdiglookup[(n%100)*2]; n/=100; } } + while (n) { if ( ( fl&CS) && (l++==3) ) { l=0; *--s=RRcomma; --o; } else { *--s=(char)(n%10)+'0'; n/=10; } } + if (n64==0) { if ((s[0]=='0') && (s!=(num+NUMSZ))) ++s; break; } + while (s!=o) if ( ( fl&CS) && (l++==3) ) { l=0; *--s=RRcomma; --o; } else { *--s='0'; } + } + + tail[0]=0; + // sign + lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + + // get the length that we copied + l = (rU32) ( (num+NUMSZ) - s ); if ( l == 0 ) { *--s='0'; l = 1; } + cs = l + (3<<24); + if (pr<0) pr = 0; + + scopy: + // get fw=leading/trailing space, pr=leading zeros + if (pr<(rS32)l) pr = l; + n = pr + lead[0] + tail[0] + tz; + if (fw<(rS32)n) fw = n; + fw -= n; + pr -= l; + + // handle right justify and leading zeros + if ( (fl&LJ)==0 ) + { + if (fl&LZ) // if leading zeros, everything is in pr + { + pr = (fw>pr)?fw:pr; + fw = 0; + } + else + { + fl &= ~CS; // if no leading zeros, then no commas + } + } + + // copy the spaces and/or zeros + if (fw+pr) + { + rS32 i; rU32 c; + + // copy leading spaces (or when doing %8.4d stuff) + if ( (fl&LJ)==0 ) while(fw>0) { cb_buf_clamp(i,fw); fw -= i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(rU32*)bf=0x20202020; bf+=4; i-=4; } while (i) {*bf++=' '; --i;} chk_cb_buf(1); } + + // copy leader + sn=lead+1; while(lead[0]) { cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + + // copy leading zeros + c = cs >> 24; cs &= 0xffffff; + cs = (fl&CS)?((rU32)(c-((pr+cs)%(c+1)))):0; + while(pr>0) { cb_buf_clamp(i,pr); pr -= i; if((fl&CS)==0) { while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(rU32*)bf=0x30303030; bf+=4; i-=4; } } while (i) { if((fl&CS) && (cs++==c)) { cs = 0; *bf++=RRcomma; } else *bf++='0'; --i; } chk_cb_buf(1); } + } + + // copy leader if there is still one + sn=lead+1; while(lead[0]) { rS32 i; cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + + // copy the string + n = l; while (n) { rS32 i; cb_buf_clamp(i,n); n-=i; RR_UNALIGNED( while(i>=4) { *(rU32*)bf=*(rU32*)s; bf+=4; s+=4; i-=4; } ) while (i) {*bf++=*s++; --i;} chk_cb_buf(1); } + + // copy trailing zeros + while(tz) { rS32 i; cb_buf_clamp(i,tz); tz -= i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(rU32*)bf=0x30303030; bf+=4; i-=4; } while (i) {*bf++='0'; --i;} chk_cb_buf(1); } + + // copy tail if there is one + sn=tail+1; while(tail[0]) { rS32 i; cb_buf_clamp(i,tail[0]); tail[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + + // handle the left justify + if (fl&LJ) if (fw>0) { while (fw) { rS32 i; cb_buf_clamp(i,fw); fw-=i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(rU32*)bf=0x20202020; bf+=4; i-=4; } while (i--) *bf++=' '; chk_cb_buf(1); } } + break; + + default: // unknown, just copy code + s = num + NUMSZ -1; *s = f[0]; + l = 1; + fw=pr=fl=0; + lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; + goto scopy; + } + ++f; + } + endfmt: + + if (!callback) + *bf = 0; + else + flush_cb(); + + done: + return tlen + (int)(bf-buf); +} + +// cleanup +#undef LJ +#undef LP +#undef LS +#undef LX +#undef LZ +#undef BI +#undef CS +#undef NG +#undef KI +#undef NUMSZ +#undef chk_cb_bufL +#undef chk_cb_buf +#undef flush_cb +#undef cb_buf_clamp + +// ============================================================================ +// wrapper functions + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( sprintf )( char * buf, char const * fmt, ... ) +{ + va_list va; + va_start( va, fmt ); + return RR_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); +} + +typedef struct RRCCS +{ + char * buf; + int count; + char tmp[ RR_SPRINTF_MIN ]; +} RRCCS; + +static char * rrclampcallback( char * buf, void * user, int len ) +{ + RRCCS * c = (RRCCS*)user; + + if ( len > c->count ) len = c->count; + + if (len) + { + if ( buf != c->buf ) + { + char * s, * d, * se; + d = c->buf; s = buf; se = buf+len; + do{ *d++ = *s++; } while (sbuf += len; + c->count -= len; + } + + if ( c->count <= 0 ) return 0; + return ( c->count >= RR_SPRINTF_MIN ) ? c->buf : c->tmp; // go direct into buffer if you can +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) +{ + RRCCS c; + int l; + + if ( count == 0 ) + return 0; + + c.buf = buf; + c.count = count; + + RR_SPRINTF_DECORATE( vsprintfcb )( rrclampcallback, &c, rrclampcallback(0,&c,0), fmt, va ); + + // zero-terminate + l = (int)( c.buf - buf ); + if ( l >= count ) // should never be greater, only equal (or less) than count + l = count - 1; + buf[l] = 0; + + return l; +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ) +{ + va_list va; + va_start( va, fmt ); + + return RR_SPRINTF_DECORATE( vsnprintf )( buf, count, fmt, va ); +} + +RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ) +{ + return RR_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); +} + +// ======================================================================= +// low level float utility functions + +#ifndef RR_SPRINTF_NOFLOAT + + // copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) + #define RRCOPYFP(dest,src) { int cn; for(cn=0;cn<8;cn++) ((char*)&dest)[cn]=((char*)&src)[cn]; } + +// get float info +static rS32 rrreal_to_parts( rS64 * bits, rS32 * expo, double value ) +{ + double d; + rS64 b = 0; + + // load value and round at the frac_digits + d = value; + + RRCOPYFP( b, d ); + + *bits = b & ((((rU64)1)<<52)-1); + *expo = ((b >> 52) & 2047)-1023; + + return (rS32)(b >> 63); +} + +static double const rrbot[23]={1e+000,1e+001,1e+002,1e+003,1e+004,1e+005,1e+006,1e+007,1e+008,1e+009,1e+010,1e+011,1e+012,1e+013,1e+014,1e+015,1e+016,1e+017,1e+018,1e+019,1e+020,1e+021,1e+022}; +static double const rrnegbot[22]={1e-001,1e-002,1e-003,1e-004,1e-005,1e-006,1e-007,1e-008,1e-009,1e-010,1e-011,1e-012,1e-013,1e-014,1e-015,1e-016,1e-017,1e-018,1e-019,1e-020,1e-021,1e-022}; +static double const rrnegboterr[22]={-5.551115123125783e-018,-2.0816681711721684e-019,-2.0816681711721686e-020,-4.7921736023859299e-021,-8.1803053914031305e-022,4.5251888174113741e-023,4.5251888174113739e-024,-2.0922560830128471e-025,-6.2281591457779853e-026,-3.6432197315497743e-027,6.0503030718060191e-028,2.0113352370744385e-029,-3.0373745563400371e-030,1.1806906454401013e-032,-7.7705399876661076e-032,2.0902213275965398e-033,-7.1542424054621921e-034,-7.1542424054621926e-035,2.4754073164739869e-036,5.4846728545790429e-037,9.2462547772103625e-038,-4.8596774326570872e-039}; +static double const rrtop[13]={1e+023,1e+046,1e+069,1e+092,1e+115,1e+138,1e+161,1e+184,1e+207,1e+230,1e+253,1e+276,1e+299}; +static double const rrnegtop[13]={1e-023,1e-046,1e-069,1e-092,1e-115,1e-138,1e-161,1e-184,1e-207,1e-230,1e-253,1e-276,1e-299}; +static double const rrtoperr[13]={8388608,6.8601809640529717e+028,-7.253143638152921e+052,-4.3377296974619174e+075,-1.5559416129466825e+098,-3.2841562489204913e+121,-3.7745893248228135e+144,-1.7356668416969134e+167,-3.8893577551088374e+190,-9.9566444326005119e+213,6.3641293062232429e+236,-5.2069140800249813e+259,-5.2504760255204387e+282}; +static double const rrnegtoperr[13]={3.9565301985100693e-040,-2.299904345391321e-063,3.6506201437945798e-086,1.1875228833981544e-109,-5.0644902316928607e-132,-6.7156837247865426e-155,-2.812077463003139e-178,-5.7778912386589953e-201,7.4997100559334532e-224,-4.6439668915134491e-247,-6.3691100762962136e-270,-9.436808465446358e-293,8.0970921678014997e-317}; + +#if defined(_MSC_VER) && (_MSC_VER<=1200) +static rU64 const rrpot[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000,100000000000, 1000000000000,10000000000000,100000000000000,1000000000000000, 10000000000000000,100000000000000000,1000000000000000000,10000000000000000000U }; +#define rrtento19th ((rU64)1000000000000000000) +#else +static rU64 const rrpot[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000ULL,100000000000ULL, 1000000000000ULL,10000000000000ULL,100000000000000ULL,1000000000000000ULL, 10000000000000000ULL,100000000000000000ULL,1000000000000000000ULL,10000000000000000000ULL }; +#define rrtento19th (1000000000000000000ULL) +#endif + +#define rrddmulthi(oh,ol,xh,yh) \ +{ \ + double ahi=0,alo,bhi=0,blo; \ + rS64 bt; \ + oh = xh * yh; \ + RRCOPYFP(bt,xh); bt&=((~(rU64)0)<<27); RRCOPYFP(ahi,bt); alo = xh-ahi; \ + RRCOPYFP(bt,yh); bt&=((~(rU64)0)<<27); RRCOPYFP(bhi,bt); blo = yh-bhi; \ + ol = ((ahi*bhi-oh)+ahi*blo+alo*bhi)+alo*blo; \ +} + +#define rrddtoS64(ob,xh,xl) \ +{ \ + double ahi=0,alo,vh,t;\ + ob = (rS64)ph;\ + vh=(double)ob;\ + ahi = ( xh - vh );\ + t = ( ahi - xh );\ + alo = (xh-(ahi-t))-(vh+t);\ + ob += (rS64)(ahi+alo+xl);\ +} + + +#define rrddrenorm(oh,ol) { double s; s=oh+ol; ol=ol-(s-oh); oh=s; } + +#define rrddmultlo(oh,ol,xh,xl,yh,yl) \ + ol = ol + ( xh*yl + xl*yh ); \ + +#define rrddmultlos(oh,ol,xh,yl) \ + ol = ol + ( xh*yl ); \ + +static void rrraise_to_power10( double *ohi, double *olo, double d, rS32 power ) // power can be -323 to +350 +{ + double ph, pl; + if ((power>=0) && (power<=22)) + { + rrddmulthi(ph,pl,d,rrbot[power]); + } + else + { + rS32 e,et,eb; + double p2h,p2l; + + e=power; if (power<0) e=-e; + et = (e*0x2c9)>>14;/* %23 */ if (et>13) et=13; eb = e-(et*23); + + ph = d; pl = 0.0; + if (power<0) + { + if (eb) { --eb; rrddmulthi(ph,pl,d,rrnegbot[eb]); rrddmultlos(ph,pl,d,rrnegboterr[eb]); } + if (et) + { + rrddrenorm(ph,pl); + --et; rrddmulthi(p2h,p2l,ph,rrnegtop[et]); rrddmultlo(p2h,p2l,ph,pl,rrnegtop[et],rrnegtoperr[et]); ph=p2h;pl=p2l; + } + } + else + { + if (eb) + { + e = eb; if (eb>22) eb=22; e -= eb; + rrddmulthi(ph,pl,d,rrbot[eb]); + if ( e ) { rrddrenorm(ph,pl); rrddmulthi(p2h,p2l,ph,rrbot[e]); rrddmultlos(p2h,p2l,rrbot[e],pl); ph=p2h;pl=p2l; } + } + if (et) + { + rrddrenorm(ph,pl); + --et; rrddmulthi(p2h,p2l,ph,rrtop[et]); rrddmultlo(p2h,p2l,ph,pl,rrtop[et],rrtoperr[et]); ph=p2h;pl=p2l; + } + } + } + rrddrenorm(ph,pl); + *ohi = ph; *olo = pl; +} + +// given a float value, returns the significant bits in bits, and the position of the +// decimal point in decimal_pos. +/-INF and NAN are specified by special values +// returned in the decimal_pos parameter. +// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 +static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * decimal_pos, double value, rU32 frac_digits ) +{ + double d; + rS64 bits = 0; + rS32 expo, e, ng, tens; + + d = value; + RRCOPYFP(bits,d); + expo = (bits >> 52) & 2047; + ng = (rS32)(bits >> 63); + if (ng) d=-d; + + if ( expo == 2047 ) // is nan or inf? + { + *start = (bits&((((rU64)1)<<52)-1)) ? "NaN" : "Inf"; + *decimal_pos = RRSPECIAL; + *len = 3; + return ng; + } + + if ( expo == 0 ) // is zero or denormal + { + if ((bits<<1)==0) // do zero + { + *decimal_pos = 1; + *start = out; + out[0] = '0'; *len = 1; + return ng; + } + // find the right expo for denormals + { + rS64 v = ((rU64)1)<<51; + while ((bits&v)==0) { --expo; v >>= 1; } + } + } + + // find the decimal exponent as well as the decimal bits of the value + { + double ph,pl; + + // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 + tens=expo-1023; tens = (tens<0)?((tens*617)/2048):(((tens*1233)/4096)+1); + + // move the significant bits into position and stick them into an int + rrraise_to_power10( &ph, &pl, d, 18-tens ); + + // get full as much precision from double-double as possible + rrddtoS64( bits, ph,pl ); + + // check if we undershot + if ( ((rU64)bits) >= rrtento19th ) ++tens; + } + + // now do the rounding in integer land + frac_digits = ( frac_digits & 0x80000000 ) ? ( (frac_digits&0x7ffffff) + 1 ) : ( tens + frac_digits ); + if ( ( frac_digits < 24 ) ) + { + rU32 dg = 1; if ((rU64)bits >= rrpot[9] ) dg=10; while( (rU64)bits >= rrpot[dg] ) { ++dg; if (dg==20) goto noround; } + if ( frac_digits < dg ) + { + rU64 r; + // add 0.5 at the right position and round + e = dg - frac_digits; + if ( (rU32)e >= 24 ) goto noround; + r = rrpot[e]; + bits = bits + (r/2); + if ( (rU64)bits >= rrpot[dg] ) ++tens; + bits /= r; + } + noround:; + } + + // kill long trailing runs of zeros + if ( bits ) + { + rU32 n; for(;;) { if ( bits<=0xffffffff ) break; if (bits%1000) goto donez; bits/=1000; } n = (rU32)bits; while ((n%1000)==0) n/=1000; bits=n; donez:; + } + + // convert to string + out += 64; + e = 0; + for(;;) + { + rU32 n; + char * o = out-8; + // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) + if (bits>=100000000) { n = (rU32)( bits % 100000000); bits /= 100000000; } else {n = (rU32)bits; bits = 0; } + while(n) { out-=2; *(rU16*)out=*(rU16*)&rrdiglookup[(n%100)*2]; n/=100; e+=2; } + if (bits==0) { if ((e) && (out[0]=='0')) { ++out; --e; } break; } + while( out!=o ) { *--out ='0'; ++e; } + } + + *decimal_pos = tens; + *start = out; + *len = e; + return ng; +} + +#undef rrddmulthi +#undef rrddrenorm +#undef rrddmultlo +#undef rrddmultlos +#undef RRSPECIAL +#undef RRCOPYFP + +#endif + +// clean up +#undef rU16 +#undef rU32 +#undef rS32 +#undef rU64 +#undef rS64 +#undef RRPUBLIC_DEC +#undef RRPUBLIC_DEF +#undef RR_SPRINTF_DECORATE +#undef RR_UNALIGNED + +#endif + +#endif From fd23d7097d8ef8a0060d3096729e5ca4906d1f35 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 02:58:16 -0800 Subject: [PATCH 414/522] rename rrsprintf to stb_sprintf --- rrsprintf.h => stb_sprintf.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rrsprintf.h => stb_sprintf.h (100%) diff --git a/rrsprintf.h b/stb_sprintf.h similarity index 100% rename from rrsprintf.h rename to stb_sprintf.h From c9fe5bac480e666fab8fd10f899f4700bc3fb3dd Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 03:48:37 -0800 Subject: [PATCH 415/522] rename all stb_sprintf identifiers to follow stb conventions --- stb.h | 1 + stb_sprintf.h | 617 +++++++++++++++++---------------- tests/grid_reachability.c | 3 + tests/stb.dsp | 4 + tests/test_c_compilation.c | 12 + tests/test_cpp_compilation.cpp | 4 + 6 files changed, 338 insertions(+), 303 deletions(-) diff --git a/stb.h b/stb.h index 6831476..4b2933c 100644 --- a/stb.h +++ b/stb.h @@ -730,6 +730,7 @@ STB_EXTERN int stb_snprintf(char *s, size_t n, const char *fmt, ...); STB_EXTERN int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v); #ifdef STB_DEFINE + int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v) { int res; diff --git a/stb_sprintf.h b/stb_sprintf.h index 62962e3..8fdc70e 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -1,5 +1,14 @@ -#ifndef RR_SPRINTF_H_INCLUDE -#define RR_SPRINTF_H_INCLUDE +// stb_sprintf - v1.00 - public domain snprintf() implementation +// originally by Jeff Roberts / RAD Game Tools, 2015/10/20 +// http://github.com/nothings/stb +// +// allowed types: sc uidBboXx p AaGgEef n +// lengths : h ll j z t I64 I32 I + + + +#ifndef STB_SPRINTF_H_INCLUDE +#define STB_SPRINTF_H_INCLUDE /* Single file sprintf replacement. @@ -22,7 +31,7 @@ the same format strings in cross platform code. It uses the standard single file trick of being both the header file and the source itself. If you just include it normally, you just get the header file function definitions. To get the code, you include -it from a C or C++ file and define RR_SPRINTF_IMPLEMENTATION first. +it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. It only uses va_args macros from the C runtime to do it's work. It does cast doubles to S64s and shifts and divides U64s, which does @@ -34,25 +43,25 @@ in 16K. API: ==== -int rrsprintf( char * buf, char const * fmt, ... ) -int rrsnprintf( char * buf, int count, char const * fmt, ... ) +int stbsp_sprintf( char * buf, char const * fmt, ... ) +int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) Convert an arg list into a buffer. rrsnprintf always returns a zero-terminated string (unlike regular snprintf). -int rrvsprintf( char * buf, char const * fmt, va_list va ) -int rrvsnprintf( char * buf, int count, char const * fmt, va_list va ) +int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) +int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) Convert a va_list arg list into a buffer. rrvsnprintf always returns a zero-terminated string (unlike regular snprintf). -int rrvsprintfcb( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) - typedef char * RRSPRINTFCB( char const * buf, void * user, int len ); - Convert into a buffer, calling back every RR_SPRINTF_MIN chars. +int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) + typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); + Convert into a buffer, calling back every STB_SPRINTF_MIN chars. Your callback can then copy the chars out, print them or whatever. This function is actually the workhorse for everything else. - The buffer you pass in must hold at least RR_SPRINTF_MIN characters. + The buffer you pass in must hold at least STB_SPRINTF_MIN characters. // you return the next buffer to use or 0 to stop converting -void rrsetseparators( char comma, char period ) +void stbsp_set_seperators( char comma, char period ) Set the comma and period characters to use. FLOATS/DOUBLES: @@ -67,10 +76,10 @@ with MSVC or GCC (but they don't match each other either). We also don't attempt to find the minimum length matching float (pre-MSVC15 doesn't either). -If you don't need float or doubles at all, define RR_SPRINTF_NOFLOAT +If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT and you'll save 4K of code space. -64-BIT INTS: +64-STBSP__INTMAXT INTS: ============ This library also supports 64-bit integers and you can use MSVC style or GCC style indicators (%I64d or %lld). It supports the C99 specifiers @@ -111,94 +120,94 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): "...512 char string..." ( 35.0x/32.5x faster!) */ -#ifdef RR_SPRINTF_STATIC -#define RRPUBLIC_DEC static -#define RRPUBLIC_DEF static +#ifdef STB_SPRINTF_STATIC +#define STBSP__PUBLICDEC static +#define STBSP__PUBLICDEF static #else #ifdef __cplusplus -#define RRPUBLIC_DEC extern "C" -#define RRPUBLIC_DEF extern "C" +#define STBSP__PUBLICDEC extern "C" +#define STBSP__PUBLICDEF extern "C" #else -#define RRPUBLIC_DEC extern -#define RRPUBLIC_DEF +#define STBSP__PUBLICDEC extern +#define STBSP__PUBLICDEF #endif #endif #include // for va_list() -#ifndef RR_SPRINTF_MIN -#define RR_SPRINTF_MIN 512 // how many characters per callback +#ifndef STB_SPRINTF_MIN +#define STB_SPRINTF_MIN 512 // how many characters per callback #endif -typedef char * RRSPRINTFCB( char * buf, void * user, int len ); +typedef char * STBSP_SPRINTFCB( char * buf, void * user, int len ); -#ifndef RR_SPRINTF_DECORATE -#define RR_SPRINTF_DECORATE(name) rr##name // define this before including if you want to change the names +#ifndef STB_SPRINTF_DECORATE +#define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names #endif -#ifndef RR_SPRINTF_IMPLEMENTATION +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ); +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ); +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( sprintf ) ( char * buf, char const * fmt, ... ); +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ); -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ); -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ); -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( sprintf ) ( char * buf, char const * fmt, ... ); -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ); +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ); +STBSP__PUBLICDEF void STB_SPRINTF_DECORATE( set_separators )( char comma, char period ); -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ); -RRPUBLIC_DEF void RR_SPRINTF_DECORATE( setseparators )( char comma, char period ); +#endif // STB_SPRINTF_H_INCLUDE -#else +#ifndef STB_SPRINTF_IMPLEMENTATION #include // for va_arg() -#define rU32 unsigned int -#define rS32 signed int +#define stbsp__uint32 unsigned int +#define stbsp__int32 signed int #ifdef _MSC_VER -#define rU64 unsigned __int64 -#define rS64 signed __int64 +#define stbsp__uint64 unsigned __int64 +#define stbsp__int64 signed __int64 #else -#define rU64 unsigned long long -#define rS64 signed long long +#define stbsp__uint64 unsigned long long +#define stbsp__int64 signed long long #endif -#define rU16 unsigned short +#define stbsp__uint16 unsigned short -#ifndef rUINTa +#ifndef stbsp__uintptr #if defined(__ppc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) -#define rUINTa rU64 +#define stbsp__uintptr stbsp__uint64 #else -#define rUINTa rU32 +#define stbsp__uintptr stbsp__uint32 #endif #endif -#ifndef RR_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) +#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) #if defined(_MSC_VER) && (_MSC_VER<1900) -#define RR_SPRINTF_MSVC_MODE +#define STB_SPRINTF_MSVC_MODE #endif #endif -#ifdef RR_SPRINTF_NOUNALIGNED // define this before inclusion to force rrsprint to always use aligned accesses -#define RR_UNALIGNED(code) +#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force rrsprint to always use aligned accesses +#define STBSP__UNALIGNED(code) #else -#define RR_UNALIGNED(code) code +#define STBSP__UNALIGNED(code) code #endif -#ifndef RR_SPRINTF_NOFLOAT +#ifndef STB_SPRINTF_NOFLOAT // internal float utility functions -static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * decimal_pos, double value, rU32 frac_digits ); -static rS32 rrreal_to_parts( rS64 * bits, rS32 * expo, double value ); -#define RRSPECIAL 0x7000 +static stbsp__int32 stbsp__real_to_str( char const * * start, stbsp__uint32 * len, char *out, stbsp__int32 * decimal_pos, double value, stbsp__uint32 frac_digits ); +static stbsp__int32 stbsp__real_to_parts( stbsp__int64 * bits, stbsp__int32 * expo, double value ); +#define STBSP__SPECIAL 0x7000 #endif -static char RRperiod='.'; -static char RRcomma=','; -static char rrdiglookup[201]="00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"; +static char stbsp__period='.'; +static char stbsp__comma=','; +static char stbsp__digitpair[201]="00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"; -RRPUBLIC_DEF void RR_SPRINTF_DECORATE( setseparators )( char pcomma, char pperiod ) +STBSP__PUBLICDEF void STB_SPRINTF_DECORATE( set_separators )( char pcomma, char pperiod ) { - RRperiod=pperiod; - RRcomma=pcomma; + stbsp__period=pperiod; + stbsp__comma=pcomma; } -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) { static char hex[]="0123456789abcdefxp"; static char hexu[]="0123456789ABCDEFXP"; @@ -210,42 +219,42 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void f = fmt; for(;;) { - rS32 fw,pr,tz; rU32 fl; + stbsp__int32 fw,pr,tz; stbsp__uint32 fl; - #define LJ 1 - #define LP 2 - #define LS 4 - #define LX 8 - #define LZ 16 - #define BI 32 - #define CS 64 - #define NG 128 - #define KI 256 - #define HW 512 + #define STBSP__LEFTJUST 1 + #define STBSP__LEADINGPLUS 2 + #define STBSP__LEADINGSPACE 4 + #define STBSP__LEADING_0X 8 + #define STBSP__LEADINGZERO 16 + #define STBSP__INTMAX 32 + #define STBSP__TRIPLET_COMMA 64 + #define STBSP__NEGATIVE 128 + #define STBSP__METRIC_SUFFIX 256 + #define STBSP__HALFWIDTH 512 // macros for the callback buffer stuff - #define chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=RR_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } - #define chk_cb_buf(bytes) { if ( callback ) { chk_cb_bufL(bytes); } } - #define flush_cb() { chk_cb_bufL(RR_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer - #define cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = RR_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } + #define stbsp__chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=STB_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } + #define stbsp__chk_cb_buf(bytes) { if ( callback ) { stbsp__chk_cb_bufL(bytes); } } + #define stbsp__flush_cb() { stbsp__chk_cb_bufL(STB_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer + #define stbsp__cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = STB_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } // fast copy everything up to the next % (or end of string) for(;;) { - while (((rUINTa)f)&3) + while (((stbsp__uintptr)f)&3) { schk1: if (f[0]=='%') goto scandd; schk2: if (f[0]==0) goto endfmt; - chk_cb_buf(1); *bf++=f[0]; ++f; + stbsp__chk_cb_buf(1); *bf++=f[0]; ++f; } for(;;) { - rU32 v,c; - v=*(rU32*)f; c=(~v)&0x80808080; + stbsp__uint32 v,c; + v=*(stbsp__uint32*)f; c=(~v)&0x80808080; if ((v-0x26262626)&c) goto schk1; if ((v-0x01010101)&c) goto schk2; - if (callback) if ((RR_SPRINTF_MIN-(int)(bf-buf))<4) goto schk1; - *(rU32*)bf=v; bf+=4; f+=4; + if (callback) if ((STB_SPRINTF_MIN-(int)(bf-buf))<4) goto schk1; + *(stbsp__uint32*)bf=v; bf+=4; f+=4; } } scandd: @@ -259,61 +268,63 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void { switch(f[0]) { - // if we have left just - case '-': fl|=LJ; ++f; continue; + // if we have left justify + case '-': fl|=STBSP__LEFTJUST; ++f; continue; // if we have leading plus - case '+': fl|=LP; ++f; continue; + case '+': fl|=STBSP__LEADINGPLUS; ++f; continue; // if we have leading space - case ' ': fl|=LS; ++f; continue; + case ' ': fl|=STBSP__LEADINGSPACE; ++f; continue; // if we have leading 0x - case '#': fl|=LX; ++f; continue; + case '#': fl|=STBSP__LEADING_0X; ++f; continue; // if we have thousand commas - case '\'': fl|=CS; ++f; continue; + case '\'': fl|=STBSP__TRIPLET_COMMA; ++f; continue; // if we have kilo marker - case '$': fl|=KI; ++f; continue; + case '$': fl|=STBSP__METRIC_SUFFIX; ++f; continue; // if we have leading zero - case '0': fl|=LZ; ++f; goto flags_done; + case '0': fl|=STBSP__LEADINGZERO; ++f; goto flags_done; default: goto flags_done; } } flags_done: // get the field width - if ( f[0] == '*' ) {fw = va_arg(va,rU32); ++f;} else { while (( f[0] >= '0' ) && ( f[0] <= '9' )) { fw = fw * 10 + f[0] - '0'; f++; } } + if ( f[0] == '*' ) {fw = va_arg(va,stbsp__uint32); ++f;} else { while (( f[0] >= '0' ) && ( f[0] <= '9' )) { fw = fw * 10 + f[0] - '0'; f++; } } // get the precision - if ( f[0]=='.' ) { ++f; if ( f[0] == '*' ) {pr = va_arg(va,rU32); ++f;} else { pr = 0; while (( f[0] >= '0' ) && ( f[0] <= '9' )) { pr = pr * 10 + f[0] - '0'; f++; } } } + if ( f[0]=='.' ) { ++f; if ( f[0] == '*' ) {pr = va_arg(va,stbsp__uint32); ++f;} else { pr = 0; while (( f[0] >= '0' ) && ( f[0] <= '9' )) { pr = pr * 10 + f[0] - '0'; f++; } } } // handle integer size overrides switch(f[0]) { // are we halfwidth? - case 'h': fl|=HW; ++f; break; + case 'h': fl|=STBSP__HALFWIDTH; ++f; break; // are we 64-bit (unix style) - case 'l': ++f; if ( f[0]=='l') { fl|=BI; ++f; } break; + case 'l': ++f; if ( f[0]=='l') { fl|=STBSP__INTMAX; ++f; } break; // are we 64-bit on intmax? (c99) - case 'j': fl|=BI; ++f; break; + case 'j': fl|=STBSP__INTMAX; ++f; break; // are we 64-bit on size_t or ptrdiff_t? (c99) - case 'z': case 't': fl|=((sizeof(char*)==8)?BI:0); ++f; break; + case 'z': case 't': fl|=((sizeof(char*)==8)?STBSP__INTMAX:0); ++f; break; // are we 64-bit (msft style) - case 'I': if ( ( f[1]=='6') && ( f[2]=='4') ) { fl|=BI; f+=3; } else if ( ( f[1]=='3') && ( f[2]=='2') ) { f+=3; } else { fl|=((sizeof(void*)==8)?BI:0); ++f; } break; + case 'I': if ( ( f[1]=='6') && ( f[2]=='4') ) { fl|=STBSP__INTMAX; f+=3; } + else if ( ( f[1]=='3') && ( f[2]=='2') ) { f+=3; } + else { fl|=((sizeof(void*)==8)?STBSP__INTMAX:0); ++f; } break; default: break; } // handle each replacement switch( f[0] ) { - #define NUMSZ 512 // big enough for e308 (with commas) or e-307 - char num[NUMSZ]; + #define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307 + char num[STBSP__NUMSZ]; char lead[8]; char tail[8]; char *s; char const *h; - rU32 l,n,cs; - rU64 n64; - #ifndef RR_SPRINTF_NOFLOAT + stbsp__uint32 l,n,cs; + stbsp__uint64 n64; + #ifndef STB_SPRINTF_NOFLOAT double fv; #endif - rS32 dp; char const * sn; + stbsp__int32 dp; char const * sn; case 's': // get the string @@ -322,16 +333,16 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void sn = s; for(;;) { - if ((((rUINTa)sn)&3)==0) break; + if ((((stbsp__uintptr)sn)&3)==0) break; lchk: if (sn[0]==0) goto ld; ++sn; } n = 0xffffffff; - if (pr>=0) { n=(rU32)(sn-s); if (n>=(rU32)pr) goto ld; n=((rU32)(pr-n))>>2; } + if (pr>=0) { n=(stbsp__uint32)(sn-s); if (n>=(stbsp__uint32)pr) goto ld; n=((stbsp__uint32)(pr-n))>>2; } while(n) { - rU32 v=*(rU32*)sn; + stbsp__uint32 v=*(stbsp__uint32*)sn; if ((v-0x01010101)&(~v)&0x80808080UL) goto lchk; sn+=4; --n; @@ -339,16 +350,16 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void goto lchk; ld: - l = (rU32) ( sn - s ); + l = (stbsp__uint32) ( sn - s ); // clamp to precision - if ( l > (rU32)pr ) l = pr; + if ( l > (stbsp__uint32)pr ) l = pr; lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; // copy the string in goto scopy; case 'c': // char // get the character - s = num + NUMSZ -1; *s = (char)va_arg(va,int); + s = num + STBSP__NUMSZ -1; *s = (char)va_arg(va,int); l = 1; lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; goto scopy; @@ -358,7 +369,7 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void *d = tlen + (int)( bf - buf ); } break; -#ifdef RR_SPRINTF_NOFLOAT +#ifdef STB_SPRINTF_NOFLOAT case 'A': // float case 'a': // hex float case 'G': // float @@ -382,30 +393,30 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void fv = va_arg(va,double); if (pr==-1) pr=6; // default is 6 // read the double into a string - if ( rrreal_to_parts( (rS64*)&n64, &dp, fv ) ) - fl |= NG; + if ( stbsp__real_to_parts( (stbsp__int64*)&n64, &dp, fv ) ) + fl |= STBSP__NEGATIVE; s = num+64; // sign - lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; - if (dp==-1023) dp=(n64)?-1022:0; else n64|=(((rU64)1)<<52); + if (dp==-1023) dp=(n64)?-1022:0; else n64|=(((stbsp__uint64)1)<<52); n64<<=(64-56); - if (pr<15) n64+=((((rU64)8)<<56)>>(pr*4)); + if (pr<15) n64+=((((stbsp__uint64)8)<<56)>>(pr*4)); // add leading chars - #ifdef RR_SPRINTF_MSVC_MODE + #ifdef STB_SPRINTF_MSVC_MODE *s++='0';*s++='x'; #else lead[1+lead[0]]='0'; lead[2+lead[0]]='x'; lead[0]+=2; #endif *s++=h[(n64>>60)&15]; n64<<=4; - if ( pr ) *s++=RRperiod; + if ( pr ) *s++=stbsp__period; sn = s; // print the bits - n = pr; if (n>13) n = 13; if (pr>(rS32)n) tz=pr-n; pr = 0; + n = pr; if (n>13) n = 13; if (pr>(stbsp__int32)n) tz=pr-n; pr = 0; while(n--) { *s++=h[(n64>>60)&15]; n64<<=4; } // print the expo @@ -431,21 +442,21 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void fv = va_arg(va,double); if (pr==-1) pr=6; else if (pr==0) pr = 1; // default is 6 // read the double into a string - if ( rrreal_to_str( &sn, &l, num, &dp, fv, (pr-1)|0x80000000 ) ) - fl |= NG; + if ( stbsp__real_to_str( &sn, &l, num, &dp, fv, (pr-1)|0x80000000 ) ) + fl |= STBSP__NEGATIVE; // clamp the precision and delete extra zeros after clamp n = pr; - if ( l > (rU32)pr ) l = pr; while ((l>1)&&(pr)&&(sn[l-1]=='0')) { --pr; --l; } + if ( l > (stbsp__uint32)pr ) l = pr; while ((l>1)&&(pr)&&(sn[l-1]=='0')) { --pr; --l; } // should we use %e - if ((dp<=-4)||(dp>(rS32)n)) + if ((dp<=-4)||(dp>(stbsp__int32)n)) { - if ( pr > (rS32)l ) pr = l-1; else if ( pr ) --pr; // when using %e, there is one digit before the decimal + if ( pr > (stbsp__int32)l ) pr = l-1; else if ( pr ) --pr; // when using %e, there is one digit before the decimal goto doexpfromg; } // this is the insane action to get the pr to match %g sematics for %f - if(dp>0) { pr=(dp<(rS32)l)?l-dp:0; } else { pr = -dp+((pr>(rS32)l)?l:pr); } + if(dp>0) { pr=(dp<(stbsp__int32)l)?l-dp:0; } else { pr = -dp+((pr>(stbsp__int32)l)?l:pr); } goto dofloatfromg; case 'E': // float @@ -458,20 +469,20 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void fv = va_arg(va,double); if (pr==-1) pr=6; // default is 6 // read the double into a string - if ( rrreal_to_str( &sn, &l, num, &dp, fv, pr|0x80000000 ) ) - fl |= NG; + if ( stbsp__real_to_str( &sn, &l, num, &dp, fv, pr|0x80000000 ) ) + fl |= STBSP__NEGATIVE; doexpfromg: tail[0]=0; - lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; - if ( dp == RRSPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } + lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + if ( dp == STBSP__SPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } s=num+64; // handle leading chars *s++=sn[0]; - if (pr) *s++=RRperiod; + if (pr) *s++=stbsp__period; // handle after decimal - if ((l-1)>(rU32)pr) l=pr+1; + if ((l-1)>(stbsp__uint32)pr) l=pr+1; for(n=1;n=100)?5:4; @@ -493,52 +504,52 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void fv = va_arg(va,double); doafloat: // do kilos - if (fl&KI) {while(fl<0x4000000) { if ((fv<1024.0) && (fv>-1024.0)) break; fv/=1024.0; fl+=0x1000000; }} + if (fl&STBSP__METRIC_SUFFIX) {while(fl<0x4000000) { if ((fv<1024.0) && (fv>-1024.0)) break; fv/=1024.0; fl+=0x1000000; }} if (pr==-1) pr=6; // default is 6 // read the double into a string - if ( rrreal_to_str( &sn, &l, num, &dp, fv, pr ) ) - fl |= NG; + if ( stbsp__real_to_str( &sn, &l, num, &dp, fv, pr ) ) + fl |= STBSP__NEGATIVE; dofloatfromg: tail[0]=0; // sign - lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; - if ( dp == RRSPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } + lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + if ( dp == STBSP__SPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } s=num+64; // handle the three decimal varieties if (dp<=0) { - rS32 i; + stbsp__int32 i; // handle 0.000*000xxxx - *s++='0'; if (pr) *s++=RRperiod; - n=-dp; if((rS32)n>pr) n=pr; i=n; while(i) { if ((((rUINTa)s)&3)==0) break; *s++='0'; --i; } while(i>=4) { *(rU32*)s=0x30303030; s+=4; i-=4; } while(i) { *s++='0'; --i; } - if ((rS32)(l+n)>pr) l=pr-n; i=l; while(i) { *s++=*sn++; --i; } + *s++='0'; if (pr) *s++=stbsp__period; + n=-dp; if((stbsp__int32)n>pr) n=pr; i=n; while(i) { if ((((stbsp__uintptr)s)&3)==0) break; *s++='0'; --i; } while(i>=4) { *(stbsp__uint32*)s=0x30303030; s+=4; i-=4; } while(i) { *s++='0'; --i; } + if ((stbsp__int32)(l+n)>pr) l=pr-n; i=l; while(i) { *s++=*sn++; --i; } tz = pr-(n+l); cs = 1 + (3<<24); // how many tens did we write (for commas below) } else { - cs = (fl&CS)?((600-(rU32)dp)%3):0; - if ((rU32)dp>=l) + cs = (fl&STBSP__TRIPLET_COMMA)?((600-(stbsp__uint32)dp)%3):0; + if ((stbsp__uint32)dp>=l) { // handle xxxx000*000.0 - n=0; for(;;) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++=sn[n]; ++n; if (n>=l) break; } } - if (n<(rU32)dp) + n=0; for(;;) { if ((fl&STBSP__TRIPLET_COMMA) && (++cs==4)) { cs = 0; *s++=stbsp__comma; } else { *s++=sn[n]; ++n; if (n>=l) break; } } + if (n<(stbsp__uint32)dp) { n = dp - n; - if ((fl&CS)==0) { while(n) { if ((((rUINTa)s)&3)==0) break; *s++='0'; --n; } while(n>=4) { *(rU32*)s=0x30303030; s+=4; n-=4; } } - while(n) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++='0'; --n; } } + if ((fl&STBSP__TRIPLET_COMMA)==0) { while(n) { if ((((stbsp__uintptr)s)&3)==0) break; *s++='0'; --n; } while(n>=4) { *(stbsp__uint32*)s=0x30303030; s+=4; n-=4; } } + while(n) { if ((fl&STBSP__TRIPLET_COMMA) && (++cs==4)) { cs = 0; *s++=stbsp__comma; } else { *s++='0'; --n; } } } cs = (int)(s-(num+64)) + (3<<24); // cs is how many tens - if (pr) { *s++=RRperiod; tz=pr;} + if (pr) { *s++=stbsp__period; tz=pr;} } else { // handle xxxxx.xxxx000*000 - n=0; for(;;) { if ((fl&CS) && (++cs==4)) { cs = 0; *s++=RRcomma; } else { *s++=sn[n]; ++n; if (n>=(rU32)dp) break; } } + n=0; for(;;) { if ((fl&STBSP__TRIPLET_COMMA) && (++cs==4)) { cs = 0; *s++=stbsp__comma; } else { *s++=sn[n]; ++n; if (n>=(stbsp__uint32)dp) break; } } cs = (int)(s-(num+64)) + (3<<24); // cs is how many tens - if (pr) *s++=RRperiod; - if ((l-dp)>(rU32)pr) l=pr+dp; + if (pr) *s++=stbsp__period; + if ((l-dp)>(stbsp__uint32)pr) l=pr+dp; while(n>24) { tail[2]="_kmgt"[fl>>24]; tail[0]=2; } } }; + if (fl&STBSP__METRIC_SUFFIX) { tail[0]=1; tail[1]=' '; { if (fl>>24) { tail[2]="_kmgt"[fl>>24]; tail[0]=2; } } }; flt_lead: // get the length that we copied - l = (rU32) ( s-(num+64) ); + l = (stbsp__uint32) ( s-(num+64) ); s=num+64; goto scopy; #endif @@ -563,21 +574,21 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void h = hex; binary: lead[0]=0; - if (fl&LX) { lead[0]=2;lead[1]='0';lead[2]=h[0xb]; } + if (fl&STBSP__LEADING_0X) { lead[0]=2;lead[1]='0';lead[2]=h[0xb]; } l=(8<<4)|(1<<8); goto radixnum; case 'o': // octal h = hexu; lead[0]=0; - if (fl&LX) { lead[0]=1;lead[1]='0'; } + if (fl&STBSP__LEADING_0X) { lead[0]=1;lead[1]='0'; } l=(3<<4)|(3<<8); goto radixnum; case 'p': // pointer - fl |= (sizeof(void*)==8)?BI:0; + fl |= (sizeof(void*)==8)?STBSP__INTMAX:0; pr = sizeof(void*)*2; - fl &= ~LZ; // 'p' only prints the pointer with zeros + fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros // drop through to X case 'X': // upper binary @@ -588,23 +599,23 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void h = hex; dohexb: l=(4<<4)|(4<<8); lead[0]=0; - if (fl&LX) { lead[0]=2;lead[1]='0';lead[2]=h[16]; } + if (fl&STBSP__LEADING_0X) { lead[0]=2;lead[1]='0';lead[2]=h[16]; } radixnum: // get the number - if ( fl&BI ) - n64 = va_arg(va,rU64); + if ( fl&STBSP__INTMAX ) + n64 = va_arg(va,stbsp__uint64); else - n64 = va_arg(va,rU32); + n64 = va_arg(va,stbsp__uint32); - s = num + NUMSZ; dp = 0; + s = num + STBSP__NUMSZ; dp = 0; // clear tail, and clear leading if value is zero tail[0]=0; if (n64==0) { lead[0]=0; if (pr==0) { l=0; cs = ( ((l>>4)&15)) << 24; goto scopy; } } // convert to string - for(;;) { *--s = h[n64&((1<<(l>>8))-1)]; n64>>=(l>>8); if ( ! ( (n64) || ((rS32) ( (num+NUMSZ) - s ) < pr ) ) ) break; if ( fl&CS) { ++l; if ((l&15)==((l>>4)&15)) { l&=~15; *--s=RRcomma; } } }; + for(;;) { *--s = h[n64&((1<<(l>>8))-1)]; n64>>=(l>>8); if ( ! ( (n64) || ((stbsp__int32) ( (num+STBSP__NUMSZ) - s ) < pr ) ) ) break; if ( fl&STBSP__TRIPLET_COMMA) { ++l; if ((l&15)==((l>>4)&15)) { l&=~15; *--s=stbsp__comma; } } }; // get the tens and the comma pos - cs = (rU32) ( (num+NUMSZ) - s ) + ( ( ((l>>4)&15)) << 24 ); + cs = (stbsp__uint32) ( (num+STBSP__NUMSZ) - s ) + ( ( ((l>>4)&15)) << 24 ); // get the length that we copied - l = (rU32) ( (num+NUMSZ) - s ); + l = (stbsp__uint32) ( (num+STBSP__NUMSZ) - s ); // copy it goto scopy; @@ -612,99 +623,99 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void case 'i': case 'd': // integer // get the integer and abs it - if ( fl&BI ) + if ( fl&STBSP__INTMAX ) { - rS64 i64 = va_arg(va,rS64); n64 = (rU64)i64; if ((f[0]!='u') && (i64<0)) { n64=(rU64)-i64; fl|=NG; } + stbsp__int64 i64 = va_arg(va,stbsp__int64); n64 = (stbsp__uint64)i64; if ((f[0]!='u') && (i64<0)) { n64=(stbsp__uint64)-i64; fl|=STBSP__NEGATIVE; } } else { - rS32 i = va_arg(va,rS32); n64 = (rU32)i; if ((f[0]!='u') && (i<0)) { n64=(rU32)-i; fl|=NG; } + stbsp__int32 i = va_arg(va,stbsp__int32); n64 = (stbsp__uint32)i; if ((f[0]!='u') && (i<0)) { n64=(stbsp__uint32)-i; fl|=STBSP__NEGATIVE; } } - #ifndef RR_SPRINTF_NOFLOAT - if (fl&KI) { if (n64<1024) pr=0; else if (pr==-1) pr=1; fv=(double)(rS64)n64; goto doafloat; } + #ifndef STB_SPRINTF_NOFLOAT + if (fl&STBSP__METRIC_SUFFIX) { if (n64<1024) pr=0; else if (pr==-1) pr=1; fv=(double)(stbsp__int64)n64; goto doafloat; } #endif // convert to string - s = num+NUMSZ; l=0; + s = num+STBSP__NUMSZ; l=0; for(;;) { // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) char * o=s-8; - if (n64>=100000000) { n = (rU32)( n64 % 100000000); n64 /= 100000000; } else {n = (rU32)n64; n64 = 0; } - if((fl&CS)==0) { while(n) { s-=2; *(rU16*)s=*(rU16*)&rrdiglookup[(n%100)*2]; n/=100; } } - while (n) { if ( ( fl&CS) && (l++==3) ) { l=0; *--s=RRcomma; --o; } else { *--s=(char)(n%10)+'0'; n/=10; } } - if (n64==0) { if ((s[0]=='0') && (s!=(num+NUMSZ))) ++s; break; } - while (s!=o) if ( ( fl&CS) && (l++==3) ) { l=0; *--s=RRcomma; --o; } else { *--s='0'; } + if (n64>=100000000) { n = (stbsp__uint32)( n64 % 100000000); n64 /= 100000000; } else {n = (stbsp__uint32)n64; n64 = 0; } + if((fl&STBSP__TRIPLET_COMMA)==0) { while(n) { s-=2; *(stbsp__uint16*)s=*(stbsp__uint16*)&stbsp__digitpair[(n%100)*2]; n/=100; } } + while (n) { if ( ( fl&STBSP__TRIPLET_COMMA) && (l++==3) ) { l=0; *--s=stbsp__comma; --o; } else { *--s=(char)(n%10)+'0'; n/=10; } } + if (n64==0) { if ((s[0]=='0') && (s!=(num+STBSP__NUMSZ))) ++s; break; } + while (s!=o) if ( ( fl&STBSP__TRIPLET_COMMA) && (l++==3) ) { l=0; *--s=stbsp__comma; --o; } else { *--s='0'; } } tail[0]=0; // sign - lead[0]=0; if (fl&NG) { lead[0]=1; lead[1]='-'; } else if (fl&LS) { lead[0]=1; lead[1]=' '; } else if (fl&LP) { lead[0]=1; lead[1]='+'; }; + lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; // get the length that we copied - l = (rU32) ( (num+NUMSZ) - s ); if ( l == 0 ) { *--s='0'; l = 1; } + l = (stbsp__uint32) ( (num+STBSP__NUMSZ) - s ); if ( l == 0 ) { *--s='0'; l = 1; } cs = l + (3<<24); if (pr<0) pr = 0; scopy: // get fw=leading/trailing space, pr=leading zeros - if (pr<(rS32)l) pr = l; + if (pr<(stbsp__int32)l) pr = l; n = pr + lead[0] + tail[0] + tz; - if (fw<(rS32)n) fw = n; + if (fw<(stbsp__int32)n) fw = n; fw -= n; pr -= l; // handle right justify and leading zeros - if ( (fl&LJ)==0 ) + if ( (fl&STBSP__LEFTJUST)==0 ) { - if (fl&LZ) // if leading zeros, everything is in pr + if (fl&STBSP__LEADINGZERO) // if leading zeros, everything is in pr { pr = (fw>pr)?fw:pr; fw = 0; } else { - fl &= ~CS; // if no leading zeros, then no commas + fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas } } // copy the spaces and/or zeros if (fw+pr) { - rS32 i; rU32 c; + stbsp__int32 i; stbsp__uint32 c; // copy leading spaces (or when doing %8.4d stuff) - if ( (fl&LJ)==0 ) while(fw>0) { cb_buf_clamp(i,fw); fw -= i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(rU32*)bf=0x20202020; bf+=4; i-=4; } while (i) {*bf++=' '; --i;} chk_cb_buf(1); } + if ( (fl&STBSP__LEFTJUST)==0 ) while(fw>0) { stbsp__cb_buf_clamp(i,fw); fw -= i; while(i) { if ((((stbsp__uintptr)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(stbsp__uint32*)bf=0x20202020; bf+=4; i-=4; } while (i) {*bf++=' '; --i;} stbsp__chk_cb_buf(1); } // copy leader - sn=lead+1; while(lead[0]) { cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + sn=lead+1; while(lead[0]) { stbsp__cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} stbsp__chk_cb_buf(1); } // copy leading zeros c = cs >> 24; cs &= 0xffffff; - cs = (fl&CS)?((rU32)(c-((pr+cs)%(c+1)))):0; - while(pr>0) { cb_buf_clamp(i,pr); pr -= i; if((fl&CS)==0) { while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(rU32*)bf=0x30303030; bf+=4; i-=4; } } while (i) { if((fl&CS) && (cs++==c)) { cs = 0; *bf++=RRcomma; } else *bf++='0'; --i; } chk_cb_buf(1); } + cs = (fl&STBSP__TRIPLET_COMMA)?((stbsp__uint32)(c-((pr+cs)%(c+1)))):0; + while(pr>0) { stbsp__cb_buf_clamp(i,pr); pr -= i; if((fl&STBSP__TRIPLET_COMMA)==0) { while(i) { if ((((stbsp__uintptr)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(stbsp__uint32*)bf=0x30303030; bf+=4; i-=4; } } while (i) { if((fl&STBSP__TRIPLET_COMMA) && (cs++==c)) { cs = 0; *bf++=stbsp__comma; } else *bf++='0'; --i; } stbsp__chk_cb_buf(1); } } // copy leader if there is still one - sn=lead+1; while(lead[0]) { rS32 i; cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + sn=lead+1; while(lead[0]) { stbsp__int32 i; stbsp__cb_buf_clamp(i,lead[0]); lead[0] -= (char)i; while (i) {*bf++=*sn++; --i;} stbsp__chk_cb_buf(1); } // copy the string - n = l; while (n) { rS32 i; cb_buf_clamp(i,n); n-=i; RR_UNALIGNED( while(i>=4) { *(rU32*)bf=*(rU32*)s; bf+=4; s+=4; i-=4; } ) while (i) {*bf++=*s++; --i;} chk_cb_buf(1); } + n = l; while (n) { stbsp__int32 i; stbsp__cb_buf_clamp(i,n); n-=i; STBSP__UNALIGNED( while(i>=4) { *(stbsp__uint32*)bf=*(stbsp__uint32*)s; bf+=4; s+=4; i-=4; } ) while (i) {*bf++=*s++; --i;} stbsp__chk_cb_buf(1); } // copy trailing zeros - while(tz) { rS32 i; cb_buf_clamp(i,tz); tz -= i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(rU32*)bf=0x30303030; bf+=4; i-=4; } while (i) {*bf++='0'; --i;} chk_cb_buf(1); } + while(tz) { stbsp__int32 i; stbsp__cb_buf_clamp(i,tz); tz -= i; while(i) { if ((((stbsp__uintptr)bf)&3)==0) break; *bf++='0'; --i; } while(i>=4) { *(stbsp__uint32*)bf=0x30303030; bf+=4; i-=4; } while (i) {*bf++='0'; --i;} stbsp__chk_cb_buf(1); } // copy tail if there is one - sn=tail+1; while(tail[0]) { rS32 i; cb_buf_clamp(i,tail[0]); tail[0] -= (char)i; while (i) {*bf++=*sn++; --i;} chk_cb_buf(1); } + sn=tail+1; while(tail[0]) { stbsp__int32 i; stbsp__cb_buf_clamp(i,tail[0]); tail[0] -= (char)i; while (i) {*bf++=*sn++; --i;} stbsp__chk_cb_buf(1); } // handle the left justify - if (fl&LJ) if (fw>0) { while (fw) { rS32 i; cb_buf_clamp(i,fw); fw-=i; while(i) { if ((((rUINTa)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(rU32*)bf=0x20202020; bf+=4; i-=4; } while (i--) *bf++=' '; chk_cb_buf(1); } } + if (fl&STBSP__LEFTJUST) if (fw>0) { while (fw) { stbsp__int32 i; stbsp__cb_buf_clamp(i,fw); fw-=i; while(i) { if ((((stbsp__uintptr)bf)&3)==0) break; *bf++=' '; --i; } while(i>=4) { *(stbsp__uint32*)bf=0x20202020; bf+=4; i-=4; } while (i--) *bf++=' '; stbsp__chk_cb_buf(1); } } break; default: // unknown, just copy code - s = num + NUMSZ -1; *s = f[0]; + s = num + STBSP__NUMSZ -1; *s = f[0]; l = 1; fw=pr=fl=0; lead[0]=0; tail[0]=0; pr = 0; dp = 0; cs = 0; @@ -717,48 +728,48 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintfcb )( RRSPRINTFCB * callback, void if (!callback) *bf = 0; else - flush_cb(); + stbsp__flush_cb(); done: return tlen + (int)(bf-buf); } // cleanup -#undef LJ -#undef LP -#undef LS -#undef LX -#undef LZ -#undef BI -#undef CS -#undef NG -#undef KI -#undef NUMSZ -#undef chk_cb_bufL -#undef chk_cb_buf -#undef flush_cb -#undef cb_buf_clamp +#undef STBSP__LEFTJUST +#undef STBSP__LEADINGPLUS +#undef STBSP__LEADINGSPACE +#undef STBSP__LEADING_0X +#undef STBSP__LEADINGZERO +#undef STBSP__INTMAX +#undef STBSP__TRIPLET_COMMA +#undef STBSP__NEGATIVE +#undef STBSP__METRIC_SUFFIX +#undef STBSP__NUMSZ +#undef stbsp__chk_cb_bufL +#undef stbsp__chk_cb_buf +#undef stbsp__flush_cb +#undef stbsp__cb_buf_clamp // ============================================================================ // wrapper functions -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( sprintf )( char * buf, char const * fmt, ... ) +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( sprintf )( char * buf, char const * fmt, ... ) { va_list va; va_start( va, fmt ); - return RR_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); + return STB_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); } -typedef struct RRCCS +typedef struct stbsp__context { char * buf; int count; - char tmp[ RR_SPRINTF_MIN ]; -} RRCCS; + char tmp[ STB_SPRINTF_MIN ]; +} stbsp__context; -static char * rrclampcallback( char * buf, void * user, int len ) +static char * stbsp__clamp_callback( char * buf, void * user, int len ) { - RRCCS * c = (RRCCS*)user; + stbsp__context * c = (stbsp__context*)user; if ( len > c->count ) len = c->count; @@ -775,12 +786,12 @@ static char * rrclampcallback( char * buf, void * user, int len ) } if ( c->count <= 0 ) return 0; - return ( c->count >= RR_SPRINTF_MIN ) ? c->buf : c->tmp; // go direct into buffer if you can + return ( c->count >= STB_SPRINTF_MIN ) ? c->buf : c->tmp; // go direct into buffer if you can } -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) { - RRCCS c; + stbsp__context c; int l; if ( count == 0 ) @@ -789,7 +800,7 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char c c.buf = buf; c.count = count; - RR_SPRINTF_DECORATE( vsprintfcb )( rrclampcallback, &c, rrclampcallback(0,&c,0), fmt, va ); + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va ); // zero-terminate l = (int)( c.buf - buf ); @@ -800,100 +811,100 @@ RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char c return l; } -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ) +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ) { va_list va; va_start( va, fmt ); - return RR_SPRINTF_DECORATE( vsnprintf )( buf, count, fmt, va ); + return STB_SPRINTF_DECORATE( vsnprintf )( buf, count, fmt, va ); } -RRPUBLIC_DEF int RR_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ) +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ) { - return RR_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); + return STB_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); } // ======================================================================= // low level float utility functions -#ifndef RR_SPRINTF_NOFLOAT +#ifndef STB_SPRINTF_NOFLOAT - // copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) - #define RRCOPYFP(dest,src) { int cn; for(cn=0;cn<8;cn++) ((char*)&dest)[cn]=((char*)&src)[cn]; } +// copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) +#define STBSP__COPYFP(dest,src) { int cn; for(cn=0;cn<8;cn++) ((char*)&dest)[cn]=((char*)&src)[cn]; } // get float info -static rS32 rrreal_to_parts( rS64 * bits, rS32 * expo, double value ) +static stbsp__int32 stbsp__real_to_parts( stbsp__int64 * bits, stbsp__int32 * expo, double value ) { double d; - rS64 b = 0; + stbsp__int64 b = 0; // load value and round at the frac_digits d = value; - RRCOPYFP( b, d ); + STBSP__COPYFP( b, d ); - *bits = b & ((((rU64)1)<<52)-1); - *expo = ((b >> 52) & 2047)-1023; + *bits = b & ((((stbsp__uint64)1)<<52)-1); + *expo = (stbsp__int32) (((b >> 52) & 2047)-1023); - return (rS32)(b >> 63); + return (stbsp__int32)(b >> 63); } -static double const rrbot[23]={1e+000,1e+001,1e+002,1e+003,1e+004,1e+005,1e+006,1e+007,1e+008,1e+009,1e+010,1e+011,1e+012,1e+013,1e+014,1e+015,1e+016,1e+017,1e+018,1e+019,1e+020,1e+021,1e+022}; -static double const rrnegbot[22]={1e-001,1e-002,1e-003,1e-004,1e-005,1e-006,1e-007,1e-008,1e-009,1e-010,1e-011,1e-012,1e-013,1e-014,1e-015,1e-016,1e-017,1e-018,1e-019,1e-020,1e-021,1e-022}; -static double const rrnegboterr[22]={-5.551115123125783e-018,-2.0816681711721684e-019,-2.0816681711721686e-020,-4.7921736023859299e-021,-8.1803053914031305e-022,4.5251888174113741e-023,4.5251888174113739e-024,-2.0922560830128471e-025,-6.2281591457779853e-026,-3.6432197315497743e-027,6.0503030718060191e-028,2.0113352370744385e-029,-3.0373745563400371e-030,1.1806906454401013e-032,-7.7705399876661076e-032,2.0902213275965398e-033,-7.1542424054621921e-034,-7.1542424054621926e-035,2.4754073164739869e-036,5.4846728545790429e-037,9.2462547772103625e-038,-4.8596774326570872e-039}; -static double const rrtop[13]={1e+023,1e+046,1e+069,1e+092,1e+115,1e+138,1e+161,1e+184,1e+207,1e+230,1e+253,1e+276,1e+299}; -static double const rrnegtop[13]={1e-023,1e-046,1e-069,1e-092,1e-115,1e-138,1e-161,1e-184,1e-207,1e-230,1e-253,1e-276,1e-299}; -static double const rrtoperr[13]={8388608,6.8601809640529717e+028,-7.253143638152921e+052,-4.3377296974619174e+075,-1.5559416129466825e+098,-3.2841562489204913e+121,-3.7745893248228135e+144,-1.7356668416969134e+167,-3.8893577551088374e+190,-9.9566444326005119e+213,6.3641293062232429e+236,-5.2069140800249813e+259,-5.2504760255204387e+282}; -static double const rrnegtoperr[13]={3.9565301985100693e-040,-2.299904345391321e-063,3.6506201437945798e-086,1.1875228833981544e-109,-5.0644902316928607e-132,-6.7156837247865426e-155,-2.812077463003139e-178,-5.7778912386589953e-201,7.4997100559334532e-224,-4.6439668915134491e-247,-6.3691100762962136e-270,-9.436808465446358e-293,8.0970921678014997e-317}; +static double const stbsp__bot[23]={1e+000,1e+001,1e+002,1e+003,1e+004,1e+005,1e+006,1e+007,1e+008,1e+009,1e+010,1e+011,1e+012,1e+013,1e+014,1e+015,1e+016,1e+017,1e+018,1e+019,1e+020,1e+021,1e+022}; +static double const stbsp__negbot[22]={1e-001,1e-002,1e-003,1e-004,1e-005,1e-006,1e-007,1e-008,1e-009,1e-010,1e-011,1e-012,1e-013,1e-014,1e-015,1e-016,1e-017,1e-018,1e-019,1e-020,1e-021,1e-022}; +static double const stbsp__negboterr[22]={-5.551115123125783e-018,-2.0816681711721684e-019,-2.0816681711721686e-020,-4.7921736023859299e-021,-8.1803053914031305e-022,4.5251888174113741e-023,4.5251888174113739e-024,-2.0922560830128471e-025,-6.2281591457779853e-026,-3.6432197315497743e-027,6.0503030718060191e-028,2.0113352370744385e-029,-3.0373745563400371e-030,1.1806906454401013e-032,-7.7705399876661076e-032,2.0902213275965398e-033,-7.1542424054621921e-034,-7.1542424054621926e-035,2.4754073164739869e-036,5.4846728545790429e-037,9.2462547772103625e-038,-4.8596774326570872e-039}; +static double const stbsp__top[13]={1e+023,1e+046,1e+069,1e+092,1e+115,1e+138,1e+161,1e+184,1e+207,1e+230,1e+253,1e+276,1e+299}; +static double const stbsp__negtop[13]={1e-023,1e-046,1e-069,1e-092,1e-115,1e-138,1e-161,1e-184,1e-207,1e-230,1e-253,1e-276,1e-299}; +static double const stbsp__toperr[13]={8388608,6.8601809640529717e+028,-7.253143638152921e+052,-4.3377296974619174e+075,-1.5559416129466825e+098,-3.2841562489204913e+121,-3.7745893248228135e+144,-1.7356668416969134e+167,-3.8893577551088374e+190,-9.9566444326005119e+213,6.3641293062232429e+236,-5.2069140800249813e+259,-5.2504760255204387e+282}; +static double const stbsp__negtoperr[13]={3.9565301985100693e-040,-2.299904345391321e-063,3.6506201437945798e-086,1.1875228833981544e-109,-5.0644902316928607e-132,-6.7156837247865426e-155,-2.812077463003139e-178,-5.7778912386589953e-201,7.4997100559334532e-224,-4.6439668915134491e-247,-6.3691100762962136e-270,-9.436808465446358e-293,8.0970921678014997e-317}; #if defined(_MSC_VER) && (_MSC_VER<=1200) -static rU64 const rrpot[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000,100000000000, 1000000000000,10000000000000,100000000000000,1000000000000000, 10000000000000000,100000000000000000,1000000000000000000,10000000000000000000U }; -#define rrtento19th ((rU64)1000000000000000000) +static stbsp__uint64 const stbsp__powten[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000,100000000000, 1000000000000,10000000000000,100000000000000,1000000000000000, 10000000000000000,100000000000000000,1000000000000000000,10000000000000000000U }; +#define stbsp__tento19th ((stbsp__uint64)1000000000000000000) #else -static rU64 const rrpot[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000ULL,100000000000ULL, 1000000000000ULL,10000000000000ULL,100000000000000ULL,1000000000000000ULL, 10000000000000000ULL,100000000000000000ULL,1000000000000000000ULL,10000000000000000000ULL }; -#define rrtento19th (1000000000000000000ULL) +static stbsp__uint64 const stbsp__powten[20]={1,10,100,1000, 10000,100000,1000000,10000000, 100000000,1000000000,10000000000ULL,100000000000ULL, 1000000000000ULL,10000000000000ULL,100000000000000ULL,1000000000000000ULL, 10000000000000000ULL,100000000000000000ULL,1000000000000000000ULL,10000000000000000000ULL }; +#define stbsp__tento19th (1000000000000000000ULL) #endif -#define rrddmulthi(oh,ol,xh,yh) \ +#define stbsp__ddmulthi(oh,ol,xh,yh) \ { \ double ahi=0,alo,bhi=0,blo; \ - rS64 bt; \ + stbsp__int64 bt; \ oh = xh * yh; \ - RRCOPYFP(bt,xh); bt&=((~(rU64)0)<<27); RRCOPYFP(ahi,bt); alo = xh-ahi; \ - RRCOPYFP(bt,yh); bt&=((~(rU64)0)<<27); RRCOPYFP(bhi,bt); blo = yh-bhi; \ + STBSP__COPYFP(bt,xh); bt&=((~(stbsp__uint64)0)<<27); STBSP__COPYFP(ahi,bt); alo = xh-ahi; \ + STBSP__COPYFP(bt,yh); bt&=((~(stbsp__uint64)0)<<27); STBSP__COPYFP(bhi,bt); blo = yh-bhi; \ ol = ((ahi*bhi-oh)+ahi*blo+alo*bhi)+alo*blo; \ } -#define rrddtoS64(ob,xh,xl) \ +#define stbsp__ddtoS64(ob,xh,xl) \ { \ double ahi=0,alo,vh,t;\ - ob = (rS64)ph;\ + ob = (stbsp__int64)ph;\ vh=(double)ob;\ ahi = ( xh - vh );\ t = ( ahi - xh );\ alo = (xh-(ahi-t))-(vh+t);\ - ob += (rS64)(ahi+alo+xl);\ + ob += (stbsp__int64)(ahi+alo+xl);\ } -#define rrddrenorm(oh,ol) { double s; s=oh+ol; ol=ol-(s-oh); oh=s; } +#define stbsp__ddrenorm(oh,ol) { double s; s=oh+ol; ol=ol-(s-oh); oh=s; } -#define rrddmultlo(oh,ol,xh,xl,yh,yl) \ +#define stbsp__ddmultlo(oh,ol,xh,xl,yh,yl) \ ol = ol + ( xh*yl + xl*yh ); \ -#define rrddmultlos(oh,ol,xh,yl) \ +#define stbsp__ddmultlos(oh,ol,xh,yl) \ ol = ol + ( xh*yl ); \ -static void rrraise_to_power10( double *ohi, double *olo, double d, rS32 power ) // power can be -323 to +350 +static void stbsp__raise_to_power10( double *ohi, double *olo, double d, stbsp__int32 power ) // power can be -323 to +350 { double ph, pl; if ((power>=0) && (power<=22)) { - rrddmulthi(ph,pl,d,rrbot[power]); + stbsp__ddmulthi(ph,pl,d,stbsp__bot[power]); } else { - rS32 e,et,eb; + stbsp__int32 e,et,eb; double p2h,p2l; e=power; if (power<0) e=-e; @@ -902,11 +913,11 @@ static void rrraise_to_power10( double *ohi, double *olo, double d, rS32 power ) ph = d; pl = 0.0; if (power<0) { - if (eb) { --eb; rrddmulthi(ph,pl,d,rrnegbot[eb]); rrddmultlos(ph,pl,d,rrnegboterr[eb]); } + if (eb) { --eb; stbsp__ddmulthi(ph,pl,d,stbsp__negbot[eb]); stbsp__ddmultlos(ph,pl,d,stbsp__negboterr[eb]); } if (et) { - rrddrenorm(ph,pl); - --et; rrddmulthi(p2h,p2l,ph,rrnegtop[et]); rrddmultlo(p2h,p2l,ph,pl,rrnegtop[et],rrnegtoperr[et]); ph=p2h;pl=p2l; + stbsp__ddrenorm(ph,pl); + --et; stbsp__ddmulthi(p2h,p2l,ph,stbsp__negtop[et]); stbsp__ddmultlo(p2h,p2l,ph,pl,stbsp__negtop[et],stbsp__negtoperr[et]); ph=p2h;pl=p2l; } } else @@ -914,17 +925,17 @@ static void rrraise_to_power10( double *ohi, double *olo, double d, rS32 power ) if (eb) { e = eb; if (eb>22) eb=22; e -= eb; - rrddmulthi(ph,pl,d,rrbot[eb]); - if ( e ) { rrddrenorm(ph,pl); rrddmulthi(p2h,p2l,ph,rrbot[e]); rrddmultlos(p2h,p2l,rrbot[e],pl); ph=p2h;pl=p2l; } + stbsp__ddmulthi(ph,pl,d,stbsp__bot[eb]); + if ( e ) { stbsp__ddrenorm(ph,pl); stbsp__ddmulthi(p2h,p2l,ph,stbsp__bot[e]); stbsp__ddmultlos(p2h,p2l,stbsp__bot[e],pl); ph=p2h;pl=p2l; } } if (et) { - rrddrenorm(ph,pl); - --et; rrddmulthi(p2h,p2l,ph,rrtop[et]); rrddmultlo(p2h,p2l,ph,pl,rrtop[et],rrtoperr[et]); ph=p2h;pl=p2l; + stbsp__ddrenorm(ph,pl); + --et; stbsp__ddmulthi(p2h,p2l,ph,stbsp__top[et]); stbsp__ddmultlo(p2h,p2l,ph,pl,stbsp__top[et],stbsp__toperr[et]); ph=p2h;pl=p2l; } } } - rrddrenorm(ph,pl); + stbsp__ddrenorm(ph,pl); *ohi = ph; *olo = pl; } @@ -932,22 +943,22 @@ static void rrraise_to_power10( double *ohi, double *olo, double d, rS32 power ) // decimal point in decimal_pos. +/-INF and NAN are specified by special values // returned in the decimal_pos parameter. // frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 -static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * decimal_pos, double value, rU32 frac_digits ) +static stbsp__int32 stbsp__real_to_str( char const * * start, stbsp__uint32 * len, char *out, stbsp__int32 * decimal_pos, double value, stbsp__uint32 frac_digits ) { double d; - rS64 bits = 0; - rS32 expo, e, ng, tens; + stbsp__int64 bits = 0; + stbsp__int32 expo, e, ng, tens; d = value; - RRCOPYFP(bits,d); - expo = (bits >> 52) & 2047; - ng = (rS32)(bits >> 63); + STBSP__COPYFP(bits,d); + expo = (stbsp__int32) ((bits >> 52) & 2047); + ng = (stbsp__int32)(bits >> 63); if (ng) d=-d; if ( expo == 2047 ) // is nan or inf? { - *start = (bits&((((rU64)1)<<52)-1)) ? "NaN" : "Inf"; - *decimal_pos = RRSPECIAL; + *start = (bits&((((stbsp__uint64)1)<<52)-1)) ? "NaN" : "Inf"; + *decimal_pos = STBSP__SPECIAL; *len = 3; return ng; } @@ -963,7 +974,7 @@ static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * d } // find the right expo for denormals { - rS64 v = ((rU64)1)<<51; + stbsp__int64 v = ((stbsp__uint64)1)<<51; while ((bits&v)==0) { --expo; v >>= 1; } } } @@ -976,29 +987,29 @@ static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * d tens=expo-1023; tens = (tens<0)?((tens*617)/2048):(((tens*1233)/4096)+1); // move the significant bits into position and stick them into an int - rrraise_to_power10( &ph, &pl, d, 18-tens ); + stbsp__raise_to_power10( &ph, &pl, d, 18-tens ); // get full as much precision from double-double as possible - rrddtoS64( bits, ph,pl ); + stbsp__ddtoS64( bits, ph,pl ); // check if we undershot - if ( ((rU64)bits) >= rrtento19th ) ++tens; + if ( ((stbsp__uint64)bits) >= stbsp__tento19th ) ++tens; } // now do the rounding in integer land frac_digits = ( frac_digits & 0x80000000 ) ? ( (frac_digits&0x7ffffff) + 1 ) : ( tens + frac_digits ); if ( ( frac_digits < 24 ) ) { - rU32 dg = 1; if ((rU64)bits >= rrpot[9] ) dg=10; while( (rU64)bits >= rrpot[dg] ) { ++dg; if (dg==20) goto noround; } + stbsp__uint32 dg = 1; if ((stbsp__uint64)bits >= stbsp__powten[9] ) dg=10; while( (stbsp__uint64)bits >= stbsp__powten[dg] ) { ++dg; if (dg==20) goto noround; } if ( frac_digits < dg ) { - rU64 r; + stbsp__uint64 r; // add 0.5 at the right position and round e = dg - frac_digits; - if ( (rU32)e >= 24 ) goto noround; - r = rrpot[e]; + if ( (stbsp__uint32)e >= 24 ) goto noround; + r = stbsp__powten[e]; bits = bits + (r/2); - if ( (rU64)bits >= rrpot[dg] ) ++tens; + if ( (stbsp__uint64)bits >= stbsp__powten[dg] ) ++tens; bits /= r; } noround:; @@ -1007,7 +1018,12 @@ static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * d // kill long trailing runs of zeros if ( bits ) { - rU32 n; for(;;) { if ( bits<=0xffffffff ) break; if (bits%1000) goto donez; bits/=1000; } n = (rU32)bits; while ((n%1000)==0) n/=1000; bits=n; donez:; + stbsp__uint32 n; + for(;;) { if ( bits<=0xffffffff ) break; if (bits%1000) goto donez; bits/=1000; } + n = (stbsp__uint32)bits; + while ((n%1000)==0) n/=1000; + bits=n; + donez:; } // convert to string @@ -1015,11 +1031,11 @@ static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * d e = 0; for(;;) { - rU32 n; + stbsp__uint32 n; char * o = out-8; // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) - if (bits>=100000000) { n = (rU32)( bits % 100000000); bits /= 100000000; } else {n = (rU32)bits; bits = 0; } - while(n) { out-=2; *(rU16*)out=*(rU16*)&rrdiglookup[(n%100)*2]; n/=100; e+=2; } + if (bits>=100000000) { n = (stbsp__uint32)( bits % 100000000); bits /= 100000000; } else {n = (stbsp__uint32)bits; bits = 0; } + while(n) { out-=2; *(stbsp__uint16*)out=*(stbsp__uint16*)&stbsp__digitpair[(n%100)*2]; n/=100; e+=2; } if (bits==0) { if ((e) && (out[0]=='0')) { ++out; --e; } break; } while( out!=o ) { *--out ='0'; ++e; } } @@ -1030,26 +1046,21 @@ static rS32 rrreal_to_str( char const * * start, rU32 * len, char *out, rS32 * d return ng; } -#undef rrddmulthi -#undef rrddrenorm -#undef rrddmultlo -#undef rrddmultlos -#undef RRSPECIAL -#undef RRCOPYFP +#undef stbsp__ddmulthi +#undef stbsp__ddrenorm +#undef stbsp__ddmultlo +#undef stbsp__ddmultlos +#undef STBSP__SPECIAL +#undef STBSP__COPYFP -#endif +#endif // STB_SPRINTF_NOFLOAT // clean up -#undef rU16 -#undef rU32 -#undef rS32 -#undef rU64 -#undef rS64 -#undef RRPUBLIC_DEC -#undef RRPUBLIC_DEF -#undef RR_SPRINTF_DECORATE -#undef RR_UNALIGNED +#undef stbsp__uint16 +#undef stbsp__uint32 +#undef stbsp__int32 +#undef stbsp__uint64 +#undef stbsp__int64 +#undef STBSP__UNALIGNED -#endif - -#endif +#endif // STB_SPRINTF_IMPLEMENTATION diff --git a/tests/grid_reachability.c b/tests/grid_reachability.c index 2bb1cd8..905f2c2 100644 --- a/tests/grid_reachability.c +++ b/tests/grid_reachability.c @@ -143,6 +143,8 @@ void end_timer(void) printf("%6.4lf ms: %s\n", tm * 1000, message); } +extern void quicktest(void); + int loc[5000][2]; int main(int argc, char **argv) { @@ -152,6 +154,7 @@ int main(int argc, char **argv) uint8 *map = stbi_load("data/map_03.png", &w, &h, 0, 1); assert(map); + quicktest(); for (j=0; j < h; ++j) for (i=0; i < w; ++i) diff --git a/tests/stb.dsp b/tests/stb.dsp index 5b32abb..05f0a7f 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -154,6 +154,10 @@ SOURCE=..\stb_rect_pack.h # End Source File # Begin Source File +SOURCE=..\stb_sprintf.h +# End Source File +# Begin Source File + SOURCE=..\stb_textedit.h # End Source File # Begin Source File diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index de25330..2a54df5 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -1,3 +1,7 @@ +#include "stb_sprintf.h" +#define STB_SPRINTF_IMPLEMENTATION +#include "stb_sprintf.h" + #define STB_PERLIN_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_DXT_IMPLEMENATION @@ -28,3 +32,11 @@ #define STBTE_DRAW_TILE(x,y,id,highlight,data) 0 #define STB_TILEMAP_EDITOR_IMPLEMENTATION #include "stb_tilemap_editor.h" + + +int quicktest(void) +{ + char buffer[999]; + stbsp_sprintf(buffer, "test%%test"); + return 0; +} \ No newline at end of file diff --git a/tests/test_cpp_compilation.cpp b/tests/test_cpp_compilation.cpp index 4e77da5..138948b 100644 --- a/tests/test_cpp_compilation.cpp +++ b/tests/test_cpp_compilation.cpp @@ -1,3 +1,7 @@ +#include "stb_sprintf.h" +#define STB_SPRINTF_IMPLEMENTATION +#include "stb_sprintf.h" + #define STB_TRUETYPE_IMPLEMENTATION #define STB_PERLIN_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION From 3f2716ace46a46e50960dfbd2ad96a71ceda4837 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 03:50:06 -0800 Subject: [PATCH 416/522] add stb_sprintf to readme --- README.md | 7 ++++--- tools/README.list | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2b17c3c..df79931 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ library | lastest version | category | LoC | description **[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 583 | simple 2D rectangle packer with decent quality +**[stb_sprintf.h](stb_sprintf.h)** | 1.00 | utility | 1066 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1330 | guts of a text editor for games etc implementing them from scratch **[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features @@ -24,11 +25,11 @@ library | lastest version | category | LoC | description **[stb_c_lexer.h](stb_c_lexer.h)** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" **[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1006 | incrementally compute reachability on grids -**[stb.h](stb.h)** | 2.28 | misc | 14276 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**[stb.h](stb.h)** | 2.28 | misc | 14277 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking -Total libraries: 19 -Total lines of C code: 48314 +Total libraries: 20 +Total lines of C code: 49381 FAQ diff --git a/tools/README.list b/tools/README.list index b5c3e5b..cc59037 100644 --- a/tools/README.list +++ b/tools/README.list @@ -4,6 +4,7 @@ stb_truetype.h | graphics | parse, decode, and rasterize ch 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 From 9953803d0cacba488c4ede50fe9d757a8da36d51 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 03:53:54 -0800 Subject: [PATCH 417/522] fix bad search-replace in comment --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 8fdc70e..4be7b14 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -79,7 +79,7 @@ doesn't either). If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT and you'll save 4K of code space. -64-STBSP__INTMAXT INTS: +64-BIT INTS: ============ This library also supports 64-bit integers and you can use MSVC style or GCC style indicators (%I64d or %lld). It supports the C99 specifiers From ca3b8d74263aae9d6299166b3f4b6864df95f79a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 04:19:53 -0800 Subject: [PATCH 418/522] add credits to readme --- README.md | 4 ++++ stb_sprintf.h | 2 -- tools/README.header.md | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index df79931..bb2b31c 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,10 @@ stb single-file public domain libraries for C/C++ +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 --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5399 | decode ogg vorbis files from file/memory to float/16-bit signed output diff --git a/stb_sprintf.h b/stb_sprintf.h index 4be7b14..23de7e4 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -5,8 +5,6 @@ // allowed types: sc uidBboXx p AaGgEef n // lengths : h ll j z t I64 I32 I - - #ifndef STB_SPRINTF_H_INCLUDE #define STB_SPRINTF_H_INCLUDE diff --git a/tools/README.header.md b/tools/README.header.md index 71e765b..847fe62 100644 --- a/tools/README.header.md +++ b/tools/README.header.md @@ -3,5 +3,9 @@ stb single-file public domain libraries for C/C++ +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 --------------------- | ---- | -------- | --- | -------------------------------- From e6e20b43dbc26ee838c45b740f4f47159a2f6b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aras=20Pranckevi=C4=8Dius?= Date: Mon, 5 Dec 2016 14:49:39 +0200 Subject: [PATCH 419/522] stb_sprintf: seperators -> separators typo in comment --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 23de7e4..a75475b 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -59,7 +59,7 @@ int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char The buffer you pass in must hold at least STB_SPRINTF_MIN characters. // you return the next buffer to use or 0 to stop converting -void stbsp_set_seperators( char comma, char period ) +void stbsp_set_separators( char comma, char period ) Set the comma and period characters to use. FLOATS/DOUBLES: From a27e577c3eb38a2f40d4c55f37c8a58d6a750397 Mon Sep 17 00:00:00 2001 From: jarikomppa Date: Mon, 5 Dec 2016 14:56:35 +0200 Subject: [PATCH 420/522] The Si prefixes for mega, giga and tera are upper case (lower case m is not mega but milli) --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 23de7e4..0be456e 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -555,7 +555,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb pr = 0; // handle k,m,g,t - if (fl&STBSP__METRIC_SUFFIX) { tail[0]=1; tail[1]=' '; { if (fl>>24) { tail[2]="_kmgt"[fl>>24]; tail[0]=2; } } }; + if (fl&STBSP__METRIC_SUFFIX) { tail[0]=1; tail[1]=' '; { if (fl>>24) { tail[2]="_kMGT"[fl>>24]; tail[0]=2; } } }; flt_lead: // get the length that we copied From 9a3f9dff13cc07752cfa95b7fcce0a50004f9c30 Mon Sep 17 00:00:00 2001 From: jarikomppa Date: Mon, 5 Dec 2016 15:08:54 +0200 Subject: [PATCH 421/522] More proper fix for the prefixes (defaults to Ki style, with define for using K style instead) --- stb_sprintf.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 0be456e..c4d9573 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -133,6 +133,9 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): #include // for va_list() +// Uncomment for old-school prefixes (KB, MB instead of KiB, MiB) with the $ format +//#define STBSP__JEDEC_PREFIX + #ifndef STB_SPRINTF_MIN #define STB_SPRINTF_MIN 512 // how many characters per callback #endif @@ -555,7 +558,23 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb pr = 0; // handle k,m,g,t - if (fl&STBSP__METRIC_SUFFIX) { tail[0]=1; tail[1]=' '; { if (fl>>24) { tail[2]="_kMGT"[fl>>24]; tail[0]=2; } } }; + if (fl&STBSP__METRIC_SUFFIX) + { + tail[0]=1; + tail[1]=' '; + { + if (fl>>24) + { + tail[2]="_KMGT"[fl>>24]; +#ifdef STBSP__JEDEC_PREFIX + tail[0]=2; +#else // SI prefix + tail[3]='i'; + tail[0]=3; +#endif + } + } + }; flt_lead: // get the length that we copied From 554e0727429cc65e187b740a484d83c7216ccce0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 06:53:36 -0800 Subject: [PATCH 422/522] fix #ifdef mistake in stb_sprintf --- README.md | 4 ++-- stb_sprintf.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb2b31c..e1e8f5f 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ library | lastest version | category | LoC | description **[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 583 | simple 2D rectangle packer with decent quality -**[stb_sprintf.h](stb_sprintf.h)** | 1.00 | utility | 1066 | fast sprintf, snprintf for C/C++ +**[stb_sprintf.h](stb_sprintf.h)** | 1.01 | utility | 1064 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1330 | guts of a text editor for games etc implementing them from scratch **[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 49381 +Total lines of C code: 49379 FAQ diff --git a/stb_sprintf.h b/stb_sprintf.h index 23de7e4..fc32543 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -1,4 +1,4 @@ -// stb_sprintf - v1.00 - public domain snprintf() implementation +// stb_sprintf - v1.01 - public domain snprintf() implementation // originally by Jeff Roberts / RAD Game Tools, 2015/10/20 // http://github.com/nothings/stb // @@ -152,7 +152,7 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE( set_separators )( char comma, char p #endif // STB_SPRINTF_H_INCLUDE -#ifndef STB_SPRINTF_IMPLEMENTATION +#ifdef STB_SPRINTF_IMPLEMENTATION #include // for va_arg() From 3e7f2d6ebddfe54bd9a9491db1349513a357bfe5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 5 Dec 2016 06:58:30 -0800 Subject: [PATCH 423/522] fix missing renames --- stb_sprintf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 4e3b3c0..7521f7e 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -43,12 +43,12 @@ API: ==== int stbsp_sprintf( char * buf, char const * fmt, ... ) int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) - Convert an arg list into a buffer. rrsnprintf always returns + Convert an arg list into a buffer. stbsp_snprintf always returns a zero-terminated string (unlike regular snprintf). int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) - Convert a va_list arg list into a buffer. rrvsnprintf always returns + Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns a zero-terminated string (unlike regular snprintf). int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) @@ -182,7 +182,7 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE( set_separators )( char comma, char p #endif #endif -#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force rrsprint to always use aligned accesses +#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses #define STBSP__UNALIGNED(code) #else #define STBSP__UNALIGNED(code) code From 0e63382be0f569f080698174a25d59f40a4d69f3 Mon Sep 17 00:00:00 2001 From: jarikomppa Date: Mon, 5 Dec 2016 17:23:01 +0200 Subject: [PATCH 424/522] A bit more involved change: support for both 1000 and 1024 divisors, and SI and JEDEC suffixes, as well as removing the space between number and suffix. --- stb_sprintf.h | 70 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index c4d9573..3842a03 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -91,8 +91,11 @@ would print 12,345. For integers and floats, you can use a "$" specifier and the number will be converted to float and then divided to get kilo, mega, giga or -tera and then printed, so "%$d" 1024 is "1.0 k", "%$.2d" 2536000 is -"2.42 m", etc. +tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is +"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn +2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three +$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the +suffix, add "_" specifier: "%_$d" -> "2.53M". In addition to octal and hexadecimal conversions, you can print integers in binary: "%b" for 256 would print 100. @@ -133,9 +136,6 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): #include // for va_list() -// Uncomment for old-school prefixes (KB, MB instead of KiB, MiB) with the $ format -//#define STBSP__JEDEC_PREFIX - #ifndef STB_SPRINTF_MIN #define STB_SPRINTF_MIN 512 // how many characters per callback #endif @@ -232,6 +232,9 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb #define STBSP__NEGATIVE 128 #define STBSP__METRIC_SUFFIX 256 #define STBSP__HALFWIDTH 512 + #define STBSP__METRIC_NOSPACE 1024 + #define STBSP__METRIC_1024 2048 + #define STBSP__METRIC_JEDEC 4096 // macros for the callback buffer stuff #define stbsp__chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=STB_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } @@ -279,8 +282,26 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb case '#': fl|=STBSP__LEADING_0X; ++f; continue; // if we have thousand commas case '\'': fl|=STBSP__TRIPLET_COMMA; ++f; continue; - // if we have kilo marker - case '$': fl|=STBSP__METRIC_SUFFIX; ++f; continue; + // if we have kilo marker (none->kilo->kibi->jedec) + case '$': + if (fl&STBSP__METRIC_SUFFIX) + { + if (fl&STBSP__METRIC_1024) + { + fl|=STBSP__METRIC_JEDEC; + } + else + { + fl|=STBSP__METRIC_1024; + } + } + else + { + fl|=STBSP__METRIC_SUFFIX; + } + ++f; continue; + // if we don't want space between metric suffix and number + case '_': fl|=STBSP__METRIC_NOSPACE; ++f; continue; // if we have leading zero case '0': fl|=STBSP__LEADINGZERO; ++f; goto flags_done; default: goto flags_done; @@ -505,7 +526,13 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb fv = va_arg(va,double); doafloat: // do kilos - if (fl&STBSP__METRIC_SUFFIX) {while(fl<0x4000000) { if ((fv<1024.0) && (fv>-1024.0)) break; fv/=1024.0; fl+=0x1000000; }} + if (fl&STBSP__METRIC_SUFFIX) + { + double divisor; + divisor=1000.0f; + if (fl&STBSP__METRIC_1024) divisor = 1024.0; + while(fl<0x4000000) { if ((fv-divisor)) break; fv/=divisor; fl+=0x1000000; } + } if (pr==-1) pr=6; // default is 6 // read the double into a string if ( stbsp__real_to_str( &sn, &l, num, &dp, fv, pr ) ) @@ -560,18 +587,27 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb // handle k,m,g,t if (fl&STBSP__METRIC_SUFFIX) { - tail[0]=1; + char idx; + idx=1; + if (fl&STBSP__METRIC_NOSPACE) + idx=0; + tail[0]=idx; tail[1]=' '; { if (fl>>24) - { - tail[2]="_KMGT"[fl>>24]; -#ifdef STBSP__JEDEC_PREFIX - tail[0]=2; -#else // SI prefix - tail[3]='i'; - tail[0]=3; -#endif + { // SI kilo is 'k', JEDEC and SI kibits are 'K'. + if (fl&STBSP__METRIC_1024) + tail[idx+1]="_KMGT"[fl>>24]; + else + tail[idx+1]="_kMGT"[fl>>24]; + idx++; + // If printing kibits and not in jedec, add the 'i'. + if (fl&STBSP__METRIC_1024&&!(fl&STBSP__METRIC_JEDEC)) + { + tail[idx+1]='i'; + idx++; + } + tail[0]=idx; } } }; From 4338a0e55e9c62eb7469f7b99dcafeeb97eb53cd Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 5 Dec 2016 21:03:05 +0000 Subject: [PATCH 425/522] Fix the check for a percent character It was matching everything less than 0x26, so could cause a minor performance loss. Also made the second if statement superfluous. --- stb_sprintf.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 4e3b3c0..e4ca291 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -247,9 +247,12 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb } for(;;) { + // Check if the next 4 bytes contain %(0x25) or end of string. + // Using the 'hasless' trick: + // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord stbsp__uint32 v,c; v=*(stbsp__uint32*)f; c=(~v)&0x80808080; - if ((v-0x26262626)&c) goto schk1; + if (((v^0x25252525)-0x01010101)&c) goto schk1; if ((v-0x01010101)&c) goto schk2; if (callback) if ((STB_SPRINTF_MIN-(int)(bf-buf))<4) goto schk1; *(stbsp__uint32*)bf=v; bf+=4; f+=4; From 13927ac386d02815f139d29f12d60382a3c33b01 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Mon, 5 Dec 2016 18:18:20 -0600 Subject: [PATCH 426/522] stb_printf.h: Reuse code for assigning lead sign. --- stb_sprintf.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 7521f7e..1f79e87 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -235,6 +235,18 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb #define stbsp__chk_cb_buf(bytes) { if ( callback ) { stbsp__chk_cb_bufL(bytes); } } #define stbsp__flush_cb() { stbsp__chk_cb_bufL(STB_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer #define stbsp__cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = STB_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } + #define stbsp__lead_sign(fl, lead) \ + lead[0] = 0;\ + if (fl&STBSP__NEGATIVE) {\ + lead[0]=1;\ + lead[1]='-';\ + } else if (fl&STBSP__LEADINGSPACE) {\ + lead[0]=1;\ + lead[1]=' ';\ + } else if (fl&STBSP__LEADINGPLUS) {\ + lead[0]=1;\ + lead[1]='+';\ + } // fast copy everything up to the next % (or end of string) for(;;) @@ -396,8 +408,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb s = num+64; - // sign - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); if (dp==-1023) dp=(n64)?-1022:0; else n64|=(((stbsp__uint64)1)<<52); n64<<=(64-56); @@ -471,7 +482,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb fl |= STBSP__NEGATIVE; doexpfromg: tail[0]=0; - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); if ( dp == STBSP__SPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } s=num+64; // handle leading chars @@ -509,8 +520,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb fl |= STBSP__NEGATIVE; dofloatfromg: tail[0]=0; - // sign - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); if ( dp == STBSP__SPECIAL ) { s=(char*)sn; cs=0; pr=0; goto scopy; } s=num+64; @@ -649,8 +659,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb } tail[0]=0; - // sign - lead[0]=0; if (fl&STBSP__NEGATIVE) { lead[0]=1; lead[1]='-'; } else if (fl&STBSP__LEADINGSPACE) { lead[0]=1; lead[1]=' '; } else if (fl&STBSP__LEADINGPLUS) { lead[0]=1; lead[1]='+'; }; + stbsp__lead_sign(fl, lead); // get the length that we copied l = (stbsp__uint32) ( (num+STBSP__NUMSZ) - s ); if ( l == 0 ) { *--s='0'; l = 1; } From ec9db6f84b39988a6a3375058e97598fe63fca4e Mon Sep 17 00:00:00 2001 From: sammyhw Date: Thu, 15 Dec 2016 23:49:19 -0500 Subject: [PATCH 427/522] allow for all 16 bits --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 345e406..025cf3b 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5719,7 +5719,7 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req // Fill this channel with default data. if (bitdepth == 16 && bpc == 16) { stbi__uint16 *q = ((stbi__uint16 *) out) + channel; - stbi_uc val = channel == 3 ? 65535 : 0; + stbi__uint16 val = channel == 3 ? 65535 : 0; for (i = 0; i < pixelCount; i++, q += 4) *q = val; } else { From 3f36b29589870d98eb1dc9945d3726eba6746728 Mon Sep 17 00:00:00 2001 From: Alejandro Pereda Date: Mon, 26 Dec 2016 16:01:50 +0100 Subject: [PATCH 428/522] Overwrites error parameter in stb_vorbis_open_memory when there is no error. This avoid confusion due to previous values. --- stb_vorbis.c | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_vorbis.c b/stb_vorbis.c index c4f24d5..91ad4bb 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -4980,6 +4980,7 @@ stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *err if (f) { *f = p; vorbis_pump_first_frame(f); + if (error) *error = VORBIS__no_error; return f; } } From a055654ee34f60072d953ee621639928b266424f Mon Sep 17 00:00:00 2001 From: Julian Raschke Date: Tue, 27 Dec 2016 11:18:26 +0100 Subject: [PATCH 429/522] Rename Point to stbv__point --- stb_vorbis.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index c4f24d5..9affd14 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1270,12 +1270,12 @@ static void neighbors(uint16 *x, int n, int *plow, int *phigh) typedef struct { uint16 x,y; -} Point; +} stbv__point; static int STBV_CDECL point_compare(const void *p, const void *q) { - Point *a = (Point *) p; - Point *b = (Point *) q; + stbv__point *a = (stbv__point *) p; + stbv__point *b = (stbv__point *) q; return a->x < b->x ? -1 : a->x > b->x; } @@ -3871,7 +3871,7 @@ static int start_decoder(vorb *f) g->book_list[j] = get_bits(f,8); return error(f, VORBIS_feature_not_supported); } else { - Point p[31*8+2]; + stbv__point p[31*8+2]; Floor1 *g = &f->floor_config[i].floor1; int max_class = -1; g->partitions = get_bits(f, 5); From f07727a28a5321c4a2e57215334a3a38ed773a33 Mon Sep 17 00:00:00 2001 From: Thomas Ruf Date: Wed, 28 Dec 2016 14:16:45 +0100 Subject: [PATCH 430/522] stb_image.h: large structures on the stack more of "allocate large structures on the stack", this time in the forgotten stbi__jpeg_test -> avoids the infamous _chkstk() when working with CRT --- stb_image.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index 345e406..2425c42 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3703,11 +3703,12 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re static int stbi__jpeg_test(stbi__context *s) { int r; - stbi__jpeg j; - j.s = s; - stbi__setup_jpeg(&j); - r = stbi__decode_jpeg_header(&j, STBI__SCAN_type); + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); stbi__rewind(s); + STBI_FREE(j); return r; } From d5ec7789bd69f77080b232039aaf95852f3380e2 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 2 Jan 2017 14:08:58 -0800 Subject: [PATCH 431/522] stb_image_resize update --- stb_image_resize.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index e9a8ab0..5214ad6 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1,4 +1,4 @@ -/* stb_image_resize - v0.91 - public domain image resizing +/* stb_image_resize - v0.92 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb @@ -154,8 +154,10 @@ ADDITIONAL CONTRIBUTORS Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix REVISIONS + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions 0.90 (2014-09-17) first released version From d0b576c47446a0ca549aa8aa6c98d66fcc9a06d8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 2 Jan 2017 15:12:18 -0800 Subject: [PATCH 432/522] update stb_truetype version --- stb_truetype.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_truetype.h b/stb_truetype.h index 22c9db4..0406a23 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.12 - public domain +// stb_truetype.h - v1.13 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -20,6 +20,7 @@ // // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling // // Misc other: // Ryan Gordon From 3d1c790e96c9f35eeabdff5b33c8fc21b81277c5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 2 Jan 2017 15:16:22 -0800 Subject: [PATCH 433/522] version history --- stb_truetype.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_truetype.h b/stb_truetype.h index 0406a23..1c3cc0b 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -52,6 +52,7 @@ // // VERSION HISTORY // +// 1.13 (2017-01-02) support OpenType fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef From cca943e78a1f1e38ce36352eae011ce91543f912 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 2 Jan 2017 15:18:52 -0800 Subject: [PATCH 434/522] version history --- stb_truetype.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_truetype.h b/stb_truetype.h index 75a8c3c..c65d3d6 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -49,10 +49,11 @@ // Higor Euripedes // Thomas Fields // Derek Vinyard +// github:IntellectualKitty // // VERSION HISTORY // -// 1.13 (2017-01-02) support OpenType fonts +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts, // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef From 19d03764b5d9a603a8cc12372d0746b76c3954ac Mon Sep 17 00:00:00 2001 From: PopPoLoPoPpo Date: Sun, 4 Dec 2016 21:14:24 +0100 Subject: [PATCH 435/522] Fix #ifndef STBI_WRITE_NO_STDIO scioe for stbi_write_hdr() stbi_write_hdr_to_func() should still be available even without STBI_WRITE_NO_STDIO, just like other formats. --- stb_image_write.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 4319c0d..c247e34 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -475,7 +475,6 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat // ************************************************************************************************* // Radiance RGBE HDR writer // by Baldur Karlsson -#ifndef STBI_WRITE_NO_STDIO #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) @@ -630,6 +629,7 @@ int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, i return stbi_write_hdr_core(&s, x, y, comp, (float *) data); } +#ifndef STBI_WRITE_NO_STDIO int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { stbi__write_context s; From 9bb7f80cb8caf128032ce628cf573e7098b45a29 Mon Sep 17 00:00:00 2001 From: Dougall Johnson Date: Tue, 3 Jan 2017 13:08:05 +1100 Subject: [PATCH 436/522] stb_truetype: Fix a couple of CFF bugs The CFF/Type 2 changes broke including without STB_TRUETYPE_IMPLEMENTATION defined, and had a typo. Sorry! --- stb_truetype.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index ad4d0d9..e1b6d4c 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -460,7 +460,7 @@ extern "C" { // private structure typedef struct { - stbtt_uint8 *data; + unsigned char *data; int cursor; int size; } stbtt__buf; @@ -1752,7 +1752,7 @@ static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) c->started = 1; } -static void stbtt__cstx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) { if (c->bounds) { stbtt__track_vertex(c, x, y); @@ -1771,7 +1771,7 @@ static void stbtt__cstx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbt static void stbtt__csctx_close_shape(stbtt__csctx *ctx) { if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) - stbtt__cstx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); } static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) @@ -1779,14 +1779,14 @@ static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) stbtt__csctx_close_shape(ctx); ctx->first_x = ctx->x = ctx->x + dx; ctx->first_y = ctx->y = ctx->y + dy; - stbtt__cstx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); } static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) { ctx->x += dx; ctx->y += dy; - stbtt__cstx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); } static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) @@ -1797,7 +1797,7 @@ static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, flo float cy2 = cy1 + dy2; ctx->x = cx2 + dx3; ctx->y = cy2 + dy3; - stbtt__cstx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); } static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) From fc682ec2ded274c2d8c65b17e7aabbaa01810634 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 15 Jan 2017 21:26:26 -0800 Subject: [PATCH 437/522] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e1e8f5f..b3c8b18 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5399 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_image.h](stb_image.h)** | 2.13 | graphics | 7099 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.12 | graphics | 3287 | parse, decode, and rasterize characters from truetype fonts +**[stb_truetype.h](stb_truetype.h)** | 1.13 | graphics | 4018 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP -**[stb_image_resize.h](stb_image_resize.h)** | 0.91 | graphics | 2578 | resize images larger/smaller with good quality +**[stb_image_resize.h](stb_image_resize.h)** | 0.92 | graphics | 2580 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 583 | simple 2D rectangle packer with decent quality **[stb_sprintf.h](stb_sprintf.h)** | 1.01 | utility | 1064 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 49379 +Total lines of C code: 50112 FAQ From d36c43f337501c0d07808166b03bffa7d72ee8ea Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 15 Jan 2017 21:41:31 -0800 Subject: [PATCH 438/522] contributing.md --- .github/CONTRIBUTING.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/CONTRIBUTING.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..78c7579 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,28 @@ +Pull Requests and Issues are both welcome. + +=== Responsiveness + +General priority order is: + +* Crashes +* Bugs +* Warnings +* Enhancements (new features, performance improvement, etc) + +Pull requests get priority over Issues. Some pull requests I take +as written; some I modify myself; some I will request changes before +accepting them. Because I've ended up supporting a lot of libraries +(20 as I write this, with more on the way), I am somewhat slow to +address things. Many issues have been around for a long time. + +=== Pull requests + +* Do NOT update the version number in the file. (This just causes conflicts.) +* Do add your name to the list of contributors. (Don't worry about the formatting.) I'll try to remember to add it if you don't, but I sometimes forget as it's an extra step. + +=== Specific libraries + +I generally do not want new file formats for stb_image because +we are trying to improve its security, so increasing its attack +surface is counter-productive. + From 2db6897d48e7bbc0877986a38e4ae3ff77a9e052 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 15 Jan 2017 21:44:34 -0800 Subject: [PATCH 439/522] contributing --- .github/CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 78c7579..5e71e87 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,6 +1,6 @@ Pull Requests and Issues are both welcome. -=== Responsiveness +# Responsiveness General priority order is: @@ -15,12 +15,12 @@ accepting them. Because I've ended up supporting a lot of libraries (20 as I write this, with more on the way), I am somewhat slow to address things. Many issues have been around for a long time. -=== Pull requests +# Pull requests * Do NOT update the version number in the file. (This just causes conflicts.) * Do add your name to the list of contributors. (Don't worry about the formatting.) I'll try to remember to add it if you don't, but I sometimes forget as it's an extra step. -=== Specific libraries +# Specific libraries I generally do not want new file formats for stb_image because we are trying to improve its security, so increasing its attack From 73b511b1a31227be972a4a7d07c694da85db81c5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 15 Jan 2017 21:49:11 -0800 Subject: [PATCH 440/522] pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..856f9f9 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,5 @@ +* Make sure you're using a special branch just for this pull request. (Sometimes people unknowingly update their submission branch, which updates the pull request with other changes.) +* Do NOT update the version number in the file. (This just causes conflicts.) +* Do add your name to the list of contributors. (Don't worry about the formatting.) I'll try to remember to add it if you don't, but I sometimes forget as it's an extra step. + +If you get something above wrong, don't fret it, it's not the end of the world. From dcdf02a59f9f67b6efd46797cbdec1d9f038cf0b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 15 Jan 2017 21:50:31 -0800 Subject: [PATCH 441/522] pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 856f9f9..cf4b4c3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,4 @@ +* Delete this list before clicking CREATE PULL REQUEST * Make sure you're using a special branch just for this pull request. (Sometimes people unknowingly update their submission branch, which updates the pull request with other changes.) * Do NOT update the version number in the file. (This just causes conflicts.) * Do add your name to the list of contributors. (Don't worry about the formatting.) I'll try to remember to add it if you don't, but I sometimes forget as it's an extra step. From 7bb64aa86784be49c6cef202009434b7264f1d39 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 15 Jan 2017 21:51:47 -0800 Subject: [PATCH 442/522] pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index cf4b4c3..2b10daa 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,5 @@ * Delete this list before clicking CREATE PULL REQUEST -* Make sure you're using a special branch just for this pull request. (Sometimes people unknowingly update their submission branch, which updates the pull request with other changes.) +* Make sure you're using a special branch just for this pull request. (Sometimes people unknowingly use a default branch, then later update that branch, which updates the pull request with the other changes if it hasn't been merged yet.) * Do NOT update the version number in the file. (This just causes conflicts.) * Do add your name to the list of contributors. (Don't worry about the formatting.) I'll try to remember to add it if you don't, but I sometimes forget as it's an extra step. From 48710234f283ec106d429a28d53436133734d121 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 15 Jan 2017 23:57:53 -0800 Subject: [PATCH 443/522] credits; 1/2/4-bit png fix; easy font spacing; NO_STDIO in image_write --- stb_easy_font.h | 11 ++++++++--- stb_image.h | 7 +++++-- stb_image_write.h | 1 + stb_sprintf.h | 20 ++++++++++++++++---- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/stb_easy_font.h b/stb_easy_font.h index 45bddc9..579dec0 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -1,4 +1,4 @@ -// stb_easy_font.h - v0.7 - bitmap font for 3D rendering - public domain +// stb_easy_font.h - v1.0 - bitmap font for 3D rendering - public domain // Sean Barrett, Feb 2015 // // Easy-to-deploy, @@ -73,9 +73,14 @@ // // VERSION HISTORY // +// (2017-01-15) 1.0 space character takes same space as numbers; fix bad spacing of 'f' // (2016-01-22) 0.7 width() supports multiline text; add height() // (2015-09-13) 0.6 #include ; updated license // (2015-02-01) 0.5 First release +// +// CONTRIBUTORS +// +// github:vassvik -- bug report #if 0 // SAMPLE CODE: @@ -109,7 +114,7 @@ struct { unsigned char h_seg; unsigned char v_seg; } stb_easy_font_charinfo[96] = { - { 5, 0, 0 }, { 3, 0, 0 }, { 5, 1, 1 }, { 7, 1, 4 }, + { 6, 0, 0 }, { 3, 0, 0 }, { 5, 1, 1 }, { 7, 1, 4 }, { 7, 3, 7 }, { 7, 6, 12 }, { 7, 8, 19 }, { 4, 16, 21 }, { 4, 17, 22 }, { 4, 19, 23 }, { 23, 21, 24 }, { 23, 22, 31 }, { 20, 23, 34 }, { 22, 23, 36 }, { 19, 24, 36 }, { 21, 25, 36 }, @@ -126,7 +131,7 @@ struct { { 7,109,165 }, { 7,118,167 }, { 6,118,172 }, { 4,120,176 }, { 6,122,177 }, { 4,122,181 }, { 23,124,182 }, { 22,129,182 }, { 4,130,182 }, { 22,131,183 }, { 6,133,187 }, { 22,135,191 }, - { 6,137,192 }, { 22,139,196 }, { 5,144,197 }, { 22,147,198 }, + { 6,137,192 }, { 22,139,196 }, { 6,144,197 }, { 22,147,198 }, { 6,150,202 }, { 19,151,206 }, { 21,152,207 }, { 6,155,209 }, { 3,160,210 }, { 23,160,211 }, { 22,164,216 }, { 22,165,220 }, { 22,167,224 }, { 22,169,228 }, { 21,171,232 }, { 21,173,233 }, diff --git a/stb_image.h b/stb_image.h index 345e406..e9f2dc5 100644 --- a/stb_image.h +++ b/stb_image.h @@ -192,7 +192,7 @@ Ryamond Barbiero Paul Du Bois Engin Manap snagar@github Michaelangel007@github Oriol Ferrer Mesia socks-the-fox Zelex@github Philipp Wiesemann Josh Tobin rlyeh@github grim210@github - Blazej Dariusz Roszkowski + Blazej Dariusz Roszkowski Dale Weiler LICENSE @@ -4842,7 +4842,10 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st void *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - ri->bits_per_channel = p->depth; + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { diff --git a/stb_image_write.h b/stb_image_write.h index c247e34..7bc2ca8 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -103,6 +103,7 @@ CREDITS: Jonas Karlsson Filip Wasil Thatcher Ulrich + github:poppolopoppo LICENSE diff --git a/stb_sprintf.h b/stb_sprintf.h index 81e757c..474426c 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -4,6 +4,9 @@ // // allowed types: sc uidBboXx p AaGgEef n // lengths : h ll j z t I64 I32 I +// +// Contributors (bugfixes): +// github:d26435 #ifndef STB_SPRINTF_H_INCLUDE #define STB_SPRINTF_H_INCLUDE @@ -118,16 +121,25 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): "...512 char string..." ( 35.0x/32.5x faster!) */ +#if defined(__has_feature) + #if __has_feature(address_sanitizer) + #define STBI__ASAN __attribute__((no_sanitize("address"))) + #endif +#endif +#ifndef STBI__ASAN +#define STBI__ASAN +#endif + #ifdef STB_SPRINTF_STATIC #define STBSP__PUBLICDEC static -#define STBSP__PUBLICDEF static +#define STBSP__PUBLICDEF static STBI__ASAN #else #ifdef __cplusplus #define STBSP__PUBLICDEC extern "C" -#define STBSP__PUBLICDEF extern "C" +#define STBSP__PUBLICDEF extern "C" STBI__ASAN #else -#define STBSP__PUBLICDEC extern -#define STBSP__PUBLICDEF +#define STBSP__PUBLICDEC extern +#define STBSP__PUBLICDEF STBI__ASAN #endif #endif From dead3815e2bebee051eb49b8f6c288245d68e11e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 00:05:58 -0800 Subject: [PATCH 444/522] credits --- stb_image.h | 16 ++++++++-------- stb_sprintf.h | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/stb_image.h b/stb_image.h index 6b4d3c0..2445413 100644 --- a/stb_image.h +++ b/stb_image.h @@ -172,9 +172,9 @@ Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) - urraka@github (animated gif) Junggon Kim (PNM comments) + github:urraka (animated gif) Junggon Kim (PNM comments) Daniel Gibson (16-bit TGA) - + socks-the-fox (16-bit TGA) Optimizations & bugfixes Fabian "ryg" Giesen Arseny Kapoulkine @@ -185,14 +185,14 @@ Dave Moore Roy Eltham Hayaki Saito Phil Jordan Won Chun Luke Graham Johan Duparc Nathan Reed the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis - Janez Zemva John Bartholomew Michal Cichon svdijk@github + Janez Zemva John Bartholomew Michal Cichon github:svdijk Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson - Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github + Laurent Gomila Cort Stratton Sergio Gonzalez github:romigrou Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan - Ryamond Barbiero Paul Du Bois Engin Manap snagar@github - Michaelangel007@github Oriol Ferrer Mesia socks-the-fox Zelex@github - Philipp Wiesemann Josh Tobin rlyeh@github grim210@github - Blazej Dariusz Roszkowski Dale Weiler + Ryamond Barbiero Paul Du Bois Engin Manap github:snagar + Michaelangel007@github Oriol Ferrer Mesia Dale Weiler github:Zelex + Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github + Blazej Dariusz Roszkowski github:sammyhw LICENSE diff --git a/stb_sprintf.h b/stb_sprintf.h index 474426c..a017ecc 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -7,6 +7,7 @@ // // Contributors (bugfixes): // github:d26435 +// github:trex78 #ifndef STB_SPRINTF_H_INCLUDE #define STB_SPRINTF_H_INCLUDE From 0bd0a9abc44957d79cbc6cfdf49565b7e95a463d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 00:11:58 -0800 Subject: [PATCH 445/522] stb_truetype: comment typo stb_c_lexer: end-of-array wrapped overflow bug --- stb_c_lexer.h | 7 +++++-- stb_sprintf.h | 11 +++++++++-- stb_truetype.h | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index e91c6c3..bcb82e1 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -30,6 +30,9 @@ // - haven't implemented support for unicode CLEX_char // - need to expand error reporting so you don't just get "CLEX_parse_error" // +// Contributors: +// Arpad Goretity (bugfix) +// // LICENSE // // This software is dual-licensed to the public domain and under the following @@ -84,7 +87,7 @@ #define STB_C_LEX_DISCARD_PREPROCESSOR Y // discard C-preprocessor directives (e.g. after prepocess // still have #line, #pragma, etc) -//#define STB_C_LEX_ISWHITE(str) ... // return length in bytes of first character if it is whitespace +//#define STB_C_LEX_ISWHITE(str) ... // return length in bytes of whitespace characters if first char is whitespace #define STB_C_LEXER_DEFINITIONS // This line prevents the header file from replacing your definitions // --END-- @@ -459,7 +462,7 @@ int stb_c_lexer_get_token(stb_lexer *lexer) int n; n = STB_C_LEX_ISWHITE(p); if (n == 0) break; - if (lexer->eof && lexer+n > lexer->eof) + if (lexer->eof && lexer->eof - lexer->parse_point < n) return stb__clex_token(tok, CLEX_parse_error, p,lexer->eof-1); p += n; } diff --git a/stb_sprintf.h b/stb_sprintf.h index a017ecc..472f805 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -769,9 +769,12 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( sprintf )( char * buf, char const * fmt, ... ) { + int result; va_list va; va_start( va, fmt ); - return STB_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); + result = STB_SPRINTF_DECORATE( vsprintfcb )( 0, 0, buf, fmt, va ); + va_end(va); + return result; } typedef struct stbsp__context @@ -827,10 +830,14 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, c STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( snprintf )( char * buf, int count, char const * fmt, ... ) { + int result; va_list va; va_start( va, fmt ); - return STB_SPRINTF_DECORATE( vsnprintf )( buf, count, fmt, va ); + result = STB_SPRINTF_DECORATE( vsnprintf )( buf, count, fmt, va ); + va_end(va); + + return result; } STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintf )( char * buf, char const * fmt, va_list va ) diff --git a/stb_truetype.h b/stb_truetype.h index e1b6d4c..aa4dd22 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -534,7 +534,7 @@ typedef struct stbrp_rect stbrp_rect; STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); // Initializes a packing context stored in the passed-in stbtt_pack_context. // Future calls using this context will pack characters into the bitmap passed -// in here: a 1-channel bitmap that is weight x height. stride_in_bytes is +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is // the distance from one row to the next (or 0 to mean they are packed tightly // together). "padding" is the amount of padding to leave between each // character (normally you want '1' for bitmaps you'll use as textures with From 96620a3a5427de86813b2fc523d535b1ade605c4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 00:51:24 -0800 Subject: [PATCH 446/522] update version numbers --- README.md | 14 +++++++------- stb_c_lexer.h | 3 ++- stb_image.h | 2 +- stb_image_write.h | 2 +- stb_sprintf.h | 2 +- stb_truetype.h | 2 +- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b3c8b18..8ddaf6d 100644 --- a/README.md +++ b/README.md @@ -12,28 +12,28 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5399 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.13 | graphics | 7099 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.13 | graphics | 4018 | parse, decode, and rasterize characters from truetype fonts -**[stb_image_write.h](stb_image_write.h)** | 1.02 | graphics | 1048 | image writing to disk: PNG, TGA, BMP +**[stb_image.h](stb_image.h)** | 2.14 | graphics | 7102 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.14 | graphics | 4018 | parse, decode, and rasterize characters from truetype fonts +**[stb_image_write.h](stb_image_write.h)** | 1.03 | graphics | 1049 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.92 | graphics | 2580 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 583 | simple 2D rectangle packer with decent quality -**[stb_sprintf.h](stb_sprintf.h)** | 1.01 | utility | 1064 | fast sprintf, snprintf for C/C++ +**[stb_sprintf.h](stb_sprintf.h)** | 1.02 | utility | 1087 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1330 | guts of a text editor for games etc implementing them from scratch **[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features **[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) -**[stb_easy_font.h](stb_easy_font.h)** | 0.7 | 3D graphics | 258 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc +**[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D graphics | 263 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.37 | game dev | 4131 | embeddable tilemap editor **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.6 | game dev | 1220 | herringbone Wang tile map generator -**[stb_c_lexer.h](stb_c_lexer.h)** | 0.07 | parsing | 816 | simplify writing parsers for C-like languages +**[stb_c_lexer.h](stb_c_lexer.h)** | 0.08 | parsing | 820 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" **[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1006 | incrementally compute reachability on grids **[stb.h](stb.h)** | 2.28 | misc | 14277 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 50112 +Total lines of C code: 50148 FAQ diff --git a/stb_c_lexer.h b/stb_c_lexer.h index bcb82e1..42ecf40 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -1,4 +1,4 @@ -// stb_c_lexer.h - v0.07 - public domain Sean Barrett 2013 +// stb_c_lexer.h - v0.08 - public domain Sean Barrett 2013 // lexer for making little C-like languages with recursive-descent parsers // // This file provides both the interface and the implementation. @@ -10,6 +10,7 @@ // suffixes on integer constants are not handled (you can override this). // // History: +// 0.08 fix bad pointer comparison // 0.07 fix mishandling of hexadecimal constants parsed by strtol // 0.06 fix missing next character after ending quote mark (Andreas Fredriksson) // 0.05 refixed get_location because github version had lost the fix diff --git a/stb_image.h b/stb_image.h index 2445413..5b334f6 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.13 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.14 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: diff --git a/stb_image_write.h b/stb_image_write.h index 7bc2ca8..ae9180b 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.03 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk diff --git a/stb_sprintf.h b/stb_sprintf.h index 472f805..f4487eb 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -1,4 +1,4 @@ -// stb_sprintf - v1.01 - public domain snprintf() implementation +// stb_sprintf - v1.02 - public domain snprintf() implementation // originally by Jeff Roberts / RAD Game Tools, 2015/10/20 // http://github.com/nothings/stb // diff --git a/stb_truetype.h b/stb_truetype.h index aa4dd22..92b9a87 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.13 - public domain +// stb_truetype.h - v1.14 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: From fc5668cdaceb4cdfdbe19a94f56d494fc3064eeb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 01:09:50 -0800 Subject: [PATCH 447/522] makefile for tests --- .travis.yml | 6 ++++++ tests/Makefile | 7 +++++++ 2 files changed, 13 insertions(+) create mode 100644 .travis.yml create mode 100644 tests/Makefile diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1e4303d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: C +install: true +script: + - cd tests + - make 32 + - make 64 diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..45db169 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,7 @@ +32: + $CC -m32 stb_vorbis.c test_c_compilation.c + $CC -m32 stb_vorbis.c test_cpp_compilation.cpp + +64: + $CC -m64 stb_vorbis.c test_c_compilation.c + $CC -m64 stb_vorbis.c test_cpp_compilation.cpp From e6268b555883e9ab9fdd38fad172a7da757393d0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 01:10:59 -0800 Subject: [PATCH 448/522] Delete release_notes.md --- release_notes.md | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 release_notes.md diff --git a/release_notes.md b/release_notes.md deleted file mode 100644 index 6712e9d..0000000 --- a/release_notes.md +++ /dev/null @@ -1,26 +0,0 @@ ----- - -2016-04-02: - -- other_libs: cro_mipmap, greatest, munit, parg, dr_flac -- stb_image_write: allocate large structures on stack for embedded (Thatcher Ulrich) -- stb_image: allocate large structures on stack for embedded (Thatcher Ulrich) -- stb_image: remove white matting for transparent PSD (stb, Oriol Ferrer Mesia) -- stb_image: fix reported channel count in PNG when req_comp is non-zero -- stb_image: re-enable SSE2 in x64 (except in gcc) -- stb_image: fix harmless typo in name (Matthew Gregan) -- stb_image: support JPEG images coded as RGB -- stb_image: bmp could return wrong channel count (snagar@github) -- stb_image: read 16-bit PNGs as 8-bit (socks-the-fox) -- stb_image_resize: fix handling of subpixel regions -- stb_image_resize: avoid warnings on asserts (Wu Shuang) -- stb_truetype: allow fabs() to be supplied by user (Simon Glass) -- stb_truetype: duplicate typedef -- stb_truetype: don't leak memory if fontsize=0 -- stb_vorbis: warnings (Thiago Goulart) -- stb_vorbis: fix multiple memory leaks of setup-memory (manxorist@github) -- stb_vorbis: avoid dropping final frame of audio data -- stb_textedit: better support for keying while holding mouse drag button (ocornut) -- stb_voxel_render: fix type of glModelview matrix (Stephen Olsen) -- stb_leakcheck: typo in comment (Lukas Meller) -- stb.h: fix _WIN32 when defining STB_THREADS From 21913be792ec40f386c955a47fb6f9c50676f0b6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 01:14:08 -0800 Subject: [PATCH 449/522] makefile --- tests/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 45db169..561051f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,7 @@ 32: - $CC -m32 stb_vorbis.c test_c_compilation.c - $CC -m32 stb_vorbis.c test_cpp_compilation.cpp + $(CC) -m32 stb_vorbis.c test_c_compilation.c + $(CC) -m32 stb_vorbis.c test_cpp_compilation.cpp 64: - $CC -m64 stb_vorbis.c test_c_compilation.c - $CC -m64 stb_vorbis.c test_cpp_compilation.cpp + $(CC) -m64 stb_vorbis.c test_c_compilation.c + $(CC) -m64 stb_vorbis.c test_cpp_compilation.cpp From e29e2bfb129845eff3043199bb8295b366aa1f59 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 01:22:16 -0800 Subject: [PATCH 450/522] makefile --- tests/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 561051f..34c8f9b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,7 @@ 32: - $(CC) -m32 stb_vorbis.c test_c_compilation.c - $(CC) -m32 stb_vorbis.c test_cpp_compilation.cpp + $(CC) -m32 -I.. ../stb_vorbis.c test_c_compilation.c + $(CC) -m32 -I.. ../stb_vorbis.c test_cpp_compilation.cpp 64: - $(CC) -m64 stb_vorbis.c test_c_compilation.c - $(CC) -m64 stb_vorbis.c test_cpp_compilation.cpp + $(CC) -m64 -I.. ../stb_vorbis.c test_c_compilation.c + $(CC) -m64 -I.. ../stb_vorbis.c test_cpp_compilation.cpp From cf6d17cd74f0bd6792cb40fea421598b28713638 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 01:28:11 -0800 Subject: [PATCH 451/522] makefile --- tests/Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 34c8f9b..412cb10 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,9 @@ +INCLUDE = -I.. + 32: - $(CC) -m32 -I.. ../stb_vorbis.c test_c_compilation.c - $(CC) -m32 -I.. ../stb_vorbis.c test_cpp_compilation.cpp + $(CC) -m32 $(INCLUDE) ../stb_vorbis.c test_c_compilation.c -lm + $(CC) -m32 $(INCLUDE) ../stb_vorbis.c test_cpp_compilation.cpp -lm 64: - $(CC) -m64 -I.. ../stb_vorbis.c test_c_compilation.c - $(CC) -m64 -I.. ../stb_vorbis.c test_cpp_compilation.cpp + $(CC) -m64 $(INCLUDE) ../stb_vorbis.c test_c_compilation.c -lm + $(CC) -m64 $(INCLUDE) ../stb_vorbis.c test_cpp_compilation.cpp -lm From a235b6cd4443ceb3d1f09f02ba8f52259b34da68 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 01:36:58 -0800 Subject: [PATCH 452/522] makefile --- .travis.yml | 1 - tests/Makefile | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1e4303d..e0dd6ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,4 @@ language: C install: true script: - cd tests - - make 32 - make 64 diff --git a/tests/Makefile b/tests/Makefile index 412cb10..ace27c8 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,9 +1,10 @@ INCLUDE = -I.. +DEFINES = -DSTB_C_LEXER_SELF_TEST 32: - $(CC) -m32 $(INCLUDE) ../stb_vorbis.c test_c_compilation.c -lm - $(CC) -m32 $(INCLUDE) ../stb_vorbis.c test_cpp_compilation.cpp -lm + $(CC) -m32 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c ../stb.c -lm + $(CC) -m32 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_cpp_compilation.cpp -lm 64: - $(CC) -m64 $(INCLUDE) ../stb_vorbis.c test_c_compilation.c -lm - $(CC) -m64 $(INCLUDE) ../stb_vorbis.c test_cpp_compilation.cpp -lm + $(CC) -m64 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c ../stb.c -lm + $(CC) -m64 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_cpp_compilation.cpp -lm From d71aea034b78a65b307b64dee4dee6453640f791 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 01:41:23 -0800 Subject: [PATCH 453/522] makefile --- tests/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index ace27c8..85a7e1d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,9 +2,9 @@ INCLUDE = -I.. DEFINES = -DSTB_C_LEXER_SELF_TEST 32: - $(CC) -m32 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c ../stb.c -lm + $(CC) -m32 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c stb.c -lm $(CC) -m32 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_cpp_compilation.cpp -lm 64: - $(CC) -m64 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c ../stb.c -lm + $(CC) -m64 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c stb.c -lm $(CC) -m64 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_cpp_compilation.cpp -lm From 7e989db555e3acba73db2dc162856ff6dcb9b7b9 Mon Sep 17 00:00:00 2001 From: themanagainstthetank <2011301000007@whu.edu.cn> Date: Mon, 16 Jan 2017 18:12:31 +0800 Subject: [PATCH 454/522] update stb_image.h int raw_data[4] to 0, or the compiler bugs --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 5b334f6..3940f38 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5375,7 +5375,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req unsigned char *tga_data; unsigned char *tga_palette = NULL; int i, j; - unsigned char raw_data[4]; + unsigned char raw_data[4] = {0}; int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; From 1b7aa1af87448e74dc9045e180a65238fbe37265 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 02:39:18 -0800 Subject: [PATCH 455/522] makefile --- tests/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 85a7e1d..c5f3af6 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,10 +1,10 @@ -INCLUDE = -I.. -DEFINES = -DSTB_C_LEXER_SELF_TEST +INCLUDES = -I.. +FLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_C_LEXER_SELF_TEST 32: - $(CC) -m32 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c stb.c -lm - $(CC) -m32 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_cpp_compilation.cpp -lm + $(CC) -m32 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c stb.c -lm + $(CC) -m32 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm 64: - $(CC) -m64 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_c_compilation.c stb.c -lm - $(CC) -m64 $(INCLUDE) $(DEFINES) ../stb_vorbis.c test_cpp_compilation.cpp -lm + $(CC) -m64 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c stb.c -lm + $(CC) -m64 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm From c09f1eebe793797dc1ef39b5947992d7481640e5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 02:47:27 -0800 Subject: [PATCH 456/522] makefile --- tests/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index c5f3af6..5d5d266 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,10 +1,10 @@ INCLUDES = -I.. -FLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_C_LEXER_SELF_TEST +FLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_DIVIDE_TEST 32: - $(CC) -m32 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c stb.c -lm + $(CC) -m32 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c -lm $(CC) -m32 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm 64: - $(CC) -m64 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c stb.c -lm + $(CC) -m64 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c -lm $(CC) -m64 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm From 1dd1b6c191df8d666b19a8a7e8dbd482619ddf99 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 02:53:36 -0800 Subject: [PATCH 457/522] makefile --- tests/Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 5d5d266..34bd057 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,10 +1,11 @@ INCLUDES = -I.. -FLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_DIVIDE_TEST +CFLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_DIVIDE_TEST +CPPFLAGS = -Wno-write-strings -DSTB_DIVIDE_TEST 32: - $(CC) -m32 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c -lm - $(CC) -m32 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm + $(CC) -m32 $(INCLUDES) $(CFLAGS) ../stb_vorbis.c test_c_compilation.c -lm + $(CC) -m32 $(INCLUDES) $(CPPFLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm 64: - $(CC) -m64 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_c_compilation.c -lm - $(CC) -m64 $(INCLUDES) $(FLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm + $(CC) -m64 $(INCLUDES) $(CFLAGS) ../stb_vorbis.c test_c_compilation.c -lm + $(CC) -m64 $(INCLUDES) $(CPPFLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm From 4d19411acdde789a29cde137b8db897c64ec3c9f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 02:58:05 -0800 Subject: [PATCH 458/522] makefile --- stb_easy_font.h | 2 +- stb_leakcheck.h | 4 ++-- stb_tilemap_editor.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_easy_font.h b/stb_easy_font.h index 579dec0..fc84fc5 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -109,7 +109,7 @@ void print_string(float x, float y, char *text, float r, float g, float b) #include #include -struct { +struct stb_easy_font_info_struct { unsigned char advance; unsigned char h_seg; unsigned char v_seg; diff --git a/stb_leakcheck.h b/stb_leakcheck.h index 6e50b22..42c0770 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -95,14 +95,14 @@ void stb_leakcheck_dumpmem(void) stb_leakcheck_malloc_info *mi = mi_head; while (mi) { if ((ptrdiff_t) mi->size >= 0) - printf("LEAKED: %s (%4d): %8z bytes at %p\n", mi->file, mi->line, mi->size, mi+1); + printf("LEAKED: %s (%4d): %8d bytes at %p\n", mi->file, mi->line, (int) mi->size, mi+1); mi = mi->next; } #ifdef STB_LEAKCHECK_SHOWALL mi = mi_head; while (mi) { if ((ptrdiff_t) mi->size < 0) - printf("FREED : %s (%4d): %8z bytes at %p\n", mi->file, mi->line, ~mi->size, mi+1); + printf("FREED : %s (%4d): %8d bytes at %p\n", mi->file, mi->line, (int) ~mi->size, mi+1); mi = mi->next; } #endif diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index cc66dd5..f16f7b3 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -3356,7 +3356,7 @@ static void stbte__toolbar(stbte_tilemap *tm, int x0, int y0, int w, int h) #define STBTE__TEXTCOLOR(n) stbte__color_table[n][STBTE__text][STBTE__idle] -static int stbte__info_value(char *label, int x, int y, int val, int digits, int id) +static int stbte__info_value(const char *label, int x, int y, int val, int digits, int id) { if (stbte__ui.event == STBTE__paint) { int off = 9-stbte__get_char_width(label[0]); From 84e2fc0a9e57d6736c800d5948f583b51f5ceeed Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 03:01:40 -0800 Subject: [PATCH 459/522] makefile --- .travis.yml | 2 +- stb_leakcheck.h | 2 +- stb_tilemap_editor.h | 3 ++- tests/Makefile | 10 +++------- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e0dd6ac..3b71802 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,4 +2,4 @@ language: C install: true script: - cd tests - - make 64 + - make all diff --git a/stb_leakcheck.h b/stb_leakcheck.h index 42c0770..0bc04a7 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -1,4 +1,4 @@ -// stb_leakcheck.h - v0.2 - quick & dirty malloc leak-checking - public domain +// stb_leakcheck.h - v0.3 - quick & dirty malloc leak-checking - public domain // LICENSE // // This software is dual-licensed to the public domain and under the following diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index f16f7b3..346fba1 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1,4 +1,4 @@ -// stb_tilemap_editor.h - v0.37 - Sean Barrett - http://nothings.org/stb +// stb_tilemap_editor.h - v0.38 - Sean Barrett - http://nothings.org/stb // placed in the public domain - not copyrighted - first released 2014-09 // // Embeddable tilemap editor for C/C++ @@ -275,6 +275,7 @@ // either approach allows cut&pasting between levels.) // // REVISION HISTORY +// 0.38 fix warning // 0.37 fix warning // 0.36 minor compiler support // 0.35 layername button changes diff --git a/tests/Makefile b/tests/Makefile index 34bd057..055ffaf 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,10 +2,6 @@ INCLUDES = -I.. CFLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_DIVIDE_TEST CPPFLAGS = -Wno-write-strings -DSTB_DIVIDE_TEST -32: - $(CC) -m32 $(INCLUDES) $(CFLAGS) ../stb_vorbis.c test_c_compilation.c -lm - $(CC) -m32 $(INCLUDES) $(CPPFLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm - -64: - $(CC) -m64 $(INCLUDES) $(CFLAGS) ../stb_vorbis.c test_c_compilation.c -lm - $(CC) -m64 $(INCLUDES) $(CPPFLAGS) ../stb_vorbis.c test_cpp_compilation.cpp -lm +all: + $(CC) $(INCLUDES) $(CFLAGS) ../stb_vorbis.c test_c_compilation.c -lm + $(CC) $(INCLUDES) $(CPPFLAGS) test_cpp_compilation.cpp -lm From 52920a2d5e15bc440b867919b4776c8c439b35e0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 16 Jan 2017 03:01:57 -0800 Subject: [PATCH 460/522] update version numbers --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8ddaf6d..c22b270 100644 --- a/README.md +++ b/README.md @@ -24,16 +24,16 @@ library | lastest version | category | LoC | description **[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor **[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) **[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D graphics | 263 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc -**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.37 | game dev | 4131 | embeddable tilemap editor +**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.38 | game dev | 4132 | embeddable tilemap editor **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **[stb_c_lexer.h](stb_c_lexer.h)** | 0.08 | parsing | 820 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" **[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1006 | incrementally compute reachability on grids **[stb.h](stb.h)** | 2.28 | misc | 14277 | helper functions for C, mostly redundant in C++; basically author's personal stuff -**[stb_leakcheck.h](stb_leakcheck.h)** | 0.2 | misc | 124 | quick-and-dirty malloc/free leak-checking +**[stb_leakcheck.h](stb_leakcheck.h)** | 0.3 | misc | 124 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 50148 +Total lines of C code: 50149 FAQ From 638267b6d5e2dde6ef5747e43fa4a27bd7927ad0 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Sun, 29 Jan 2017 12:30:38 -0800 Subject: [PATCH 461/522] Floating point rounding causes stbir__calculate_sample_range_upsample to sometimes think it needs one more scanline than it really does. This patch adds one extra entry to the ringbuffer to avoid the problem. --- stb_image_resize.h | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 5214ad6..220cce4 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -533,10 +533,11 @@ typedef struct int horizontal_num_contributors; int vertical_num_contributors; - int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. int ring_buffer_first_scanline; int ring_buffer_last_scanline; - int ring_buffer_begin_index; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer float* ring_buffer; float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. @@ -1411,6 +1412,8 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) int ring_buffer_index; float* ring_buffer; + stbir_info->ring_buffer_last_scanline = n; + if (stbir_info->ring_buffer_begin_index < 0) { ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; @@ -1418,15 +1421,13 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) } else { - ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width; + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); } ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); - stbir_info->ring_buffer_last_scanline = n; - return ring_buffer; } @@ -1678,9 +1679,9 @@ static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n } // Get the specified scan line from the ring buffer. -static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_size, int ring_buffer_length) +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) { - int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_size; + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); } @@ -1865,7 +1866,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in int alpha_channel = stbir_info->alpha_channel; int type = stbir_info->type; int colorspace = stbir_info->colorspace; - int kernel_pixel_width = stbir_info->vertical_filter_pixel_width; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; void* output_data = stbir_info->output_data; float* encode_buffer = stbir_info->encode_buffer; int decode = STBIR__DECODE(type, colorspace); @@ -1900,7 +1901,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1913,7 +1914,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1927,7 +1928,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1942,7 +1943,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1958,7 +1959,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1981,7 +1982,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; float* vertical_coefficients = stbir_info->vertical_coefficients; int channels = stbir_info->channels; - int kernel_pixel_width = stbir_info->vertical_filter_pixel_width; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; void* output_data = stbir_info->output_data; float* horizontal_buffer = stbir_info->horizontal_buffer; int coefficient_width = stbir_info->vertical_coefficient_width; @@ -2005,7 +2006,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, int coefficient_group = coefficient_width * contributor; float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); switch (channels) { case 1: @@ -2071,7 +2072,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); - STBIR_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); if (stbir_info->ring_buffer_begin_index >= 0) { @@ -2090,7 +2091,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) else { stbir_info->ring_buffer_first_scanline++; - stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; } } } @@ -2148,7 +2149,7 @@ static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessar else { stbir_info->ring_buffer_first_scanline++; - stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; } } } @@ -2172,7 +2173,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); - STBIR_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); if (out_last_scanline < 0 || out_first_scanline >= output_h) continue; @@ -2246,13 +2247,16 @@ static stbir_uint32 stbir__calculate_memory(stbir__info *info) info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); - info->ring_buffer_size = info->output_w * info->channels * filter_height * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); info->encode_buffer_size = info->output_w * info->channels * sizeof(float); STBIR_ASSERT(info->horizontal_filter != 0); From 7ef6ac1b351b7335489daba2bd69d18c149db911 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 29 Jan 2017 18:16:38 -0800 Subject: [PATCH 462/522] added redundant pg_test.c just in case --- tests/pg_test/pg_test.c | 124 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 tests/pg_test/pg_test.c diff --git a/tests/pg_test/pg_test.c b/tests/pg_test/pg_test.c new file mode 100644 index 0000000..c028d5f --- /dev/null +++ b/tests/pg_test/pg_test.c @@ -0,0 +1,124 @@ +#define STB_DEFINE +#include "stb.h" +#define STB_PG_IMPLEMENTATION +#include "stb_pg.h" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +static float *hf; +static int hf_width = 10001; +static int hf_height = 10001; + +static float get_height(float x, float y) +{ + float h00,h01,h10,h11,h0,h1; + int ix,iy; + if (x < 0) x = 0; + if (x > hf_width-1) x = (float) hf_width-1; + if (y < 0) y = 0; + if (y > hf_height-1) y = (float) hf_height-1; + ix = (int) x; x -= ix; + iy = (int) y; y -= iy; + h00 = hf[(iy+0)*hf_height+(ix+0)]; + h10 = hf[(iy+0)*hf_height+(ix+1)]; + h01 = hf[(iy+1)*hf_height+(ix+0)]; + h11 = hf[(iy+1)*hf_height+(ix+1)]; + h0 = stb_lerp(y, h00, h01); + h1 = stb_lerp(y, h10, h11); + return stb_lerp(x, h0, h1); +} + +void stbpg_tick(float dt) +{ + int i=0,j=0; + int step = 1; + + glUseProgram(0); + + glClearColor(0.6f,0.7f,1.0f,1.0f); + glClearDepth(1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); +#if 1 + glEnable(GL_CULL_FACE); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60.0, 1920/1080.0f, 0.02f, 8000.0f); + //glOrtho(-8,8,-6,6, -100, 100); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glRotatef(-90, 1,0,0); // z-up + + { + float x,y; + stbpg_get_mouselook(&x,&y); + glRotatef(-y, 1,0,0); + glRotatef(-x, 0,0,1); + } + + { + static float cam_x = 1000; + static float cam_y = 1000; + static float cam_z = 700; + float x=0,y=0; + stbpg_get_keymove(&x,&y); + cam_x += x*dt*5.0f; + cam_y += y*dt*5.0f; + glTranslatef(-cam_x, -cam_y, -cam_z); + if (cam_x >= 0 && cam_x < hf_width && cam_y >= 0 && cam_y < hf_height) + cam_z = get_height(cam_x, cam_y) + 1.65f; // average eye height in meters + } + + for (j=501; j+1 < 1500+0*hf_height; j += step) { + glBegin(GL_QUAD_STRIP); + for (i=501; i < 1500+0*hf_width; i += step) { + static int flip=0; + if (flip) + glColor3f(0.5,0.5,0.5); + else + glColor3f(0.4f,0.4f,0.4f); + flip = !flip; + glVertex3f((float) i, (float) j+step,hf[(j+step)*hf_width+i]); + glVertex3f((float) i, (float) j ,hf[ j *hf_width+i]); + } + glEnd(); + } + + glBegin(GL_LINES); + glColor3f(1,0,0); glVertex3f(10,0,0); glVertex3f(0,0,0); + glColor3f(0,1,0); glVertex3f(0,10,0); glVertex3f(0,0,0); + glColor3f(0,0,1); glVertex3f(0,0,10); glVertex3f(0,0,0); + glEnd(); +#endif +} + +void stbpg_main(int argc, char **argv) +{ + int i,j; + + #if 0 + int w,h,c; + unsigned short *data = stbi_load_16("c:/x/ned_1m/test2.png", &w, &h, &c, 1); + stb_filewrite("c:/x/ned_1m/x73_y428_10012_10012.bin", data, w*h*2); + #else + unsigned short *data = stb_file("c:/x/ned_1m/x73_y428_10012_10012.bin", NULL); + int w=10012, h = 10012; + #endif + + hf = malloc(hf_width * hf_height * 4); + for (j=0; j < hf_height; ++j) + for (i=0; i < hf_width; ++i) + hf[j*hf_width+i] = data[j*w+i] / 32.0f; + + stbpg_gl_compat_version(1,1); + stbpg_windowed("terrain_edit", 1920, 1080); + stbpg_run(); + + return; +} From f5519a8f85389ed1c063fab3a459581d10ef4aa8 Mon Sep 17 00:00:00 2001 From: Cort Date: Mon, 13 Feb 2017 18:23:53 -0800 Subject: [PATCH 463/522] stbtt: chardata can be const in GetBakedQuad() and GetPackedQuad() --- stb_truetype.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 92b9a87..f2e3750 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -50,6 +50,7 @@ // Higor Euripedes // Thomas Fields // Derek Vinyard +// Cort Stratton // // VERSION HISTORY // @@ -494,7 +495,7 @@ typedef struct float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -594,7 +595,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h // To use with PackFontRangesGather etc., you must set it before calls // call to PackFontRangesGatherRects. -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -3287,11 +3288,11 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo return bottom_y; } -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; + const stbtt_bakedchar *b = chardata + char_index; int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); @@ -3735,10 +3736,10 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontda return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) { float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; + const stbtt_packedchar *b = chardata + char_index; if (align_to_integer) { float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); From 552c548a0e6b978ba329e2702d7713327b40fd74 Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Thu, 2 Mar 2017 18:06:10 -0800 Subject: [PATCH 464/522] stb_image: JPEG: Convert RGB to grayscale properly --- stb_image.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3940f38..b3944b5 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3596,7 +3596,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp // determine actual number of components to generate n = req_comp ? req_comp : z->s->img_n; - if (z->s->img_n == 3 && n < 3) + if (z->s->img_n == 3 && n < 3 && z->rgb != 3) decode_n = 1; else decode_n = z->s->img_n; @@ -3674,11 +3674,19 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp out += n; } } else { - stbi_uc *y = coutput[0]; - if (n == 1) - for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; - else - for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + if (z->rgb == 3) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } } } stbi__cleanup_jpeg(z); From cb7ffb2408ca11fd05a13f9dff658911e7aaa050 Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Thu, 2 Mar 2017 18:19:21 -0800 Subject: [PATCH 465/522] stb_image: Update contributors --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index b3944b5..ed11d38 100644 --- a/stb_image.h +++ b/stb_image.h @@ -192,7 +192,7 @@ Ryamond Barbiero Paul Du Bois Engin Manap github:snagar Michaelangel007@github Oriol Ferrer Mesia Dale Weiler github:Zelex Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github - Blazej Dariusz Roszkowski github:sammyhw + Blazej Dariusz Roszkowski github:sammyhw Jeremy Sawicki LICENSE From 34fa37bbb4d690843b1d51c311c1f240a5d0570e Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Thu, 2 Mar 2017 21:40:40 -0800 Subject: [PATCH 466/522] stb_image: JPEG: Accept any component IDs --- stb_image.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3940f38..0b5989b 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3004,13 +3004,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) for (i=0; i < s->img_n; ++i) { static unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); - if (z->img_comp[i].id != i+1) // JFIF requires - if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files! - // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format) - if (z->img_comp[i].id != rgb[i]) - return stbi__err("bad component ID","Corrupt JPEG"); - ++z->rgb; - } + if (z->img_comp[i].id == rgb[i]) + ++z->rgb; q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); From e08d39867195b9e18367a2d90d98784b618340d8 Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Thu, 2 Mar 2017 22:32:30 -0800 Subject: [PATCH 467/522] stb_image: JPEG: Accept 16-bit quantization tables --- stb_image.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3940f38..5dc58ad 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1730,7 +1730,7 @@ typedef struct stbi__context *s; stbi__huffman huff_dc[4]; stbi__huffman huff_ac[4]; - stbi_uc dequant[4][64]; + stbi__uint16 dequant[4][64]; stbi__int16 fast_ac[4][1 << FAST_BITS]; // sizes for components, interleaved MCUs @@ -1975,7 +1975,7 @@ static stbi_uc stbi__jpeg_dezigzag[64+15] = }; // decode one 64-entry block-- -static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi_uc *dequant) +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) { int diff,dc,k; int t; @@ -2831,7 +2831,7 @@ static int stbi__parse_entropy_coded_data(stbi__jpeg *z) } } -static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant) +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) { int i; for (i=0; i < 64; ++i) @@ -2875,11 +2875,11 @@ static int stbi__process_marker(stbi__jpeg *z, int m) int q = stbi__get8(z->s); int p = q >> 4; int t = q & 15,i; - if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); for (i=0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); - L -= 65; + z->dequant[t][stbi__jpeg_dezigzag[i]] = p == 0 ? stbi__get8(z->s) : stbi__get16be(z->s); + L -= p == 0 ? 65 : 129; } return L==0; From 344c3f73d59c159f939ebdf01f2d89654727499d Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Thu, 2 Mar 2017 23:10:03 -0800 Subject: [PATCH 468/522] stb_image: JPEG: Accept fill bytes in stbi__grow_buffer_unsafe --- stb_image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_image.h b/stb_image.h index 3940f38..282f358 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1851,6 +1851,7 @@ static void stbi__grow_buffer_unsafe(stbi__jpeg *j) int b = j->nomore ? 0 : stbi__get8(j->s); if (b == 0xff) { int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; From 6f5677946c9853be9ea87bfa13facc205d27fe05 Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Thu, 2 Mar 2017 23:48:02 -0800 Subject: [PATCH 469/522] stb_image: JPEG: Accept non-zero junk bytes at the end of image data --- stb_image.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3940f38..2ba2c2e 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3123,8 +3123,6 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) if (x == 255) { j->marker = stbi__get8(j->s); break; - } else if (x != 0) { - return stbi__err("junk before marker", "Corrupt JPEG"); } } // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 From 2219a6da29b978e783ff0d155433ec95eedd56ce Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Fri, 3 Mar 2017 00:13:27 -0800 Subject: [PATCH 470/522] stb_image: JPEG: Accept DNL segment --- stb_image.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stb_image.h b/stb_image.h index 3940f38..705f87a 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3129,6 +3129,11 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) } // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) stbi__err("bad DNL height", "Corrupt JPEG"); } else { if (!stbi__process_marker(j, m)) return 0; } From f5f7dc02a1308817e94f43f783bd3abef8706271 Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Fri, 3 Mar 2017 01:11:34 -0800 Subject: [PATCH 471/522] stb_image: JPEG: Provide failure reason for unknown marker --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 3940f38..171148d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2917,7 +2917,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m) stbi__skip(z->s, stbi__get16be(z->s)-2); return 1; } - return 0; + return stbi__err("unknown marker","Corrupt JPEG"); } // after we see SOS From d2de2be10fdb1cf459e194b40302af8f6a8a0c7b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 05:48:37 -0800 Subject: [PATCH 472/522] vorbis: propagate errors better on seek failure (e.g. when coarse seek fails) --- stb_vorbis.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index c4f24d5..dd364c8 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -275,7 +275,7 @@ extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); // do not need to seek to EXACTLY the target sample when using get_samples_*, // you can also use seek_frame(). -extern void stb_vorbis_seek_start(stb_vorbis *f); +extern int stb_vorbis_seek_start(stb_vorbis *f); // this function is equivalent to stb_vorbis_seek(f,0) extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); @@ -3484,11 +3484,13 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) return right - left; } -static void vorbis_pump_first_frame(stb_vorbis *f) +static int vorbis_pump_first_frame(stb_vorbis *f) { - int len, right, left; - if (vorbis_decode_packet(f, &len, &left, &right)) + int len, right, left, res; + res = vorbis_decode_packet(f, &len, &left, &right); + if (res) vorbis_finish_frame(f, len, left, right); + return res; } #ifndef STB_VORBIS_NO_PUSHDATA_API @@ -4615,8 +4617,9 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) // starting from the start is handled differently if (sample_number <= left.last_decoded_sample) { - stb_vorbis_seek_start(f); - return 1; + if (stb_vorbis_seek_start(f)) + return 1; + return 0; } while (left.page_end != right.page_start) { @@ -4717,7 +4720,10 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) skip(f, f->segments[i]); // start decoding (optimizable - this frame is generally discarded) - vorbis_pump_first_frame(f); + if (!vorbis_pump_first_frame(f)) + return 0; + if (f->current_loc > sample_number) + return error(f, VORBIS_seek_failed); return 1; error: @@ -4808,14 +4814,14 @@ int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) return 1; } -void stb_vorbis_seek_start(stb_vorbis *f) +int stb_vorbis_seek_start(stb_vorbis *f) { - if (IS_PUSH_MODE(f)) { error(f, VORBIS_invalid_api_mixing); return; } + if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); } set_file_offset(f, f->first_audio_page_offset); f->previous_length = 0; f->first_decode = TRUE; f->next_seg = -1; - vorbis_pump_first_frame(f); + return vorbis_pump_first_frame(f); } unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) From 46046238b8097abfd1905bc39c9222b3d4b5fb13 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 06:54:11 -0800 Subject: [PATCH 473/522] rename Point data structure as suggested in pull request --- stb_vorbis.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 0eaed25..871133e 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1270,13 +1270,13 @@ static void neighbors(uint16 *x, int n, int *plow, int *phigh) // this has been repurposed so y is now the original index instead of y typedef struct { - uint16 x,y; -} stbv__point; + uint16 x,id; +} stbv__floor_ordering; static int STBV_CDECL point_compare(const void *p, const void *q) { - stbv__point *a = (stbv__point *) p; - stbv__point *b = (stbv__point *) q; + stbv__floor_ordering *a = (stbv__floor_ordering *) p; + stbv__floor_ordering *b = (stbv__floor_ordering *) q; return a->x < b->x ? -1 : a->x > b->x; } @@ -3874,7 +3874,7 @@ static int start_decoder(vorb *f) g->book_list[j] = get_bits(f,8); return error(f, VORBIS_feature_not_supported); } else { - stbv__point p[31*8+2]; + stbv__floor_ordering p[31*8+2]; Floor1 *g = &f->floor_config[i].floor1; int max_class = -1; g->partitions = get_bits(f, 5); @@ -3910,11 +3910,11 @@ static int start_decoder(vorb *f) // precompute the sorting for (j=0; j < g->values; ++j) { p[j].x = g->Xlist[j]; - p[j].y = j; + p[j].id = j; } qsort(p, g->values, sizeof(p[0]), point_compare); for (j=0; j < g->values; ++j) - g->sorted_order[j] = (uint8) p[j].y; + g->sorted_order[j] = (uint8) p[j].id; // precompute the neighbors for (j=2; j < g->values; ++j) { int low,hi; From f88e2a8e7ba48c963f82dec86094a6cfa1e1556c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 06:58:14 -0800 Subject: [PATCH 474/522] update version --- stb_vorbis.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 871133e..985eff7 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.09 - public domain +// Ogg Vorbis audio decoder - v1.10 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -37,6 +37,7 @@ // manxorist@github saga musix // // Partial history: +// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory // 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version // 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame // 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const @@ -5353,6 +5354,7 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; avoid discarding last frame of audio data From e248e309546e546314115637fd6516b3e326a1c9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 07:53:07 -0800 Subject: [PATCH 475/522] change license to public-domain AND mit (based on twitter vote) --- stb_c_lexer.h | 45 ++++++++++++++++++++++++++++++--- stb_connected_components.h | 45 ++++++++++++++++++++++++++++++--- stb_divide.h | 46 +++++++++++++++++++++++++++++++--- stb_dxt.h | 47 ++++++++++++++++++++++++++++++++--- stb_easy_font.h | 46 +++++++++++++++++++++++++++++++--- stb_image.h | 47 ++++++++++++++++++++++++++++++++--- stb_image_resize.h | 46 +++++++++++++++++++++++++++++++--- stb_leakcheck.h | 47 ++++++++++++++++++++++++++++++++--- stb_perlin.h | 46 +++++++++++++++++++++++++++++++--- stb_rect_pack.h | 46 +++++++++++++++++++++++++++++++--- stb_sprintf.h | 47 +++++++++++++++++++++++++++++++++++ stb_textedit.h | 46 +++++++++++++++++++++++++++++++--- stb_tilemap_editor.h | 46 +++++++++++++++++++++++++++++++--- stb_truetype.h | 46 +++++++++++++++++++++++++++++++--- stb_vorbis.c | 50 ++++++++++++++++++++++++++++++++----- stb_voxel_render.h | 46 +++++++++++++++++++++++++++++++--- stretchy_buffer.h | 51 ++++++++++++++++++++++++++++++++++---- 17 files changed, 739 insertions(+), 54 deletions(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index 42ecf40..987984b 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -36,9 +36,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for licensing information. #ifndef STB_C_LEXER_DEFINITIONS // to change the default parsing rules, copy the following lines @@ -818,3 +816,44 @@ int main(int argc, char **argv) return 0; } #endif +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_connected_components.h b/stb_connected_components.h index 778b5f9..04b28de 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -52,9 +52,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for licensing information. // // ALGORITHM // @@ -1004,3 +1002,44 @@ static void stbcc__build_clumps_for_cluster(stbcc_grid *g, int cx, int cy) } #endif // STB_CONNECTED_COMPONENTS_IMPLEMENTATION +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_divide.h b/stb_divide.h index d1702f3..24d0788 100644 --- a/stb_divide.h +++ b/stb_divide.h @@ -78,9 +78,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for licensing information. #ifndef INCLUDE_STB_DIVIDE_H @@ -377,3 +375,45 @@ int main(int argc, char **argv) #endif // STB_DIVIDE_TEST #endif // STB_DIVIDE_IMPLEMENTATION #endif // INCLUDE_STB_DIVIDE_H + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_dxt.h b/stb_dxt.h index 0a8b34a..c03c8d0 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -19,9 +19,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for licensing information. #ifndef STB_INCLUDE_STB_DXT_H #define STB_INCLUDE_STB_DXT_H @@ -626,5 +624,46 @@ void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int a stb__CompressColorBlock(dest,(unsigned char*) src,mode); } #endif // STB_DXT_IMPLEMENTATION - #endif // STB_INCLUDE_STB_DXT_H + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_easy_font.h b/stb_easy_font.h index fc84fc5..506054f 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -67,9 +67,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for licensing information. // // VERSION HISTORY // @@ -261,3 +259,45 @@ static int stb_easy_font_height(char *text) return (int) ceil(y + (nonempty_line ? 12 : 0)); } #endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_image.h b/stb_image.h index 5b334f6..83ad9ba 100644 --- a/stb_image.h +++ b/stb_image.h @@ -197,9 +197,7 @@ LICENSE -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish, and distribute this file as you see fit. + See end of file for licensing information. */ @@ -7100,3 +7098,46 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int 0.50 (2006-11-19) first released version */ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_image_resize.h b/stb_image_resize.h index 5214ad6..8e8a73e 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -163,9 +163,7 @@ LICENSE - This software is dual-licensed to the public domain and under the following - license: you are granted a perpetual, irrevocable license to copy, modify, - publish, and distribute this file as you see fit. + See end of file for license information. TODO Don't decode all of the image data when only processing a partial tile @@ -2578,3 +2576,45 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int } #endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_leakcheck.h b/stb_leakcheck.h index 0bc04a7..587c5e0 100644 --- a/stb_leakcheck.h +++ b/stb_leakcheck.h @@ -1,9 +1,7 @@ // stb_leakcheck.h - v0.3 - quick & dirty malloc leak-checking - public domain // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file. #ifdef STB_LEAKCHECK_IMPLEMENTATION #undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once @@ -122,3 +120,46 @@ extern void stb_leakcheck_free(void *ptr); extern void stb_leakcheck_dumpmem(void); #endif // INCLUDE_STB_LEAKCHECK_H + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_perlin.h b/stb_perlin.h index 0dac7d9..fa144b2 100644 --- a/stb_perlin.h +++ b/stb_perlin.h @@ -3,9 +3,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file. // // // to create the implementation, @@ -180,3 +178,45 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z return stb__perlin_lerp(n0,n1,u); } #endif // STB_PERLIN_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_rect_pack.h b/stb_rect_pack.h index c75527d..178e750 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -43,9 +43,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. ////////////////////////////////////////////////////////////////////////////// // @@ -581,3 +579,45 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); } #endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_sprintf.h b/stb_sprintf.h index f4487eb..540d13e 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -8,6 +8,10 @@ // Contributors (bugfixes): // github:d26435 // github:trex78 +// +// LICENSE: +// +// See end of file for license information. #ifndef STB_SPRINTF_H_INCLUDE #define STB_SPRINTF_H_INCLUDE @@ -1085,3 +1089,46 @@ static stbsp__int32 stbsp__real_to_str( char const * * start, stbsp__uint32 * le #undef STBSP__UNALIGNED #endif // STB_SPRINTF_IMPLEMENTATION + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_textedit.h b/stb_textedit.h index 27a6993..c5a3e7c 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -17,9 +17,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. // // // DEPENDENCIES @@ -1328,3 +1326,45 @@ static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state #endif #endif//STB_TEXTEDIT_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 346fba1..94cff66 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -317,9 +317,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. @@ -4130,3 +4128,45 @@ void stbte_mouse_sdl(stbte_tilemap *tm, const void *sdl_event, float xs, float y } #endif // STB_TILEMAP_EDITOR_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_truetype.h b/stb_truetype.h index 92b9a87..df62356 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -69,9 +69,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. // // USAGE // @@ -4016,3 +4014,45 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_vorbis.c b/stb_vorbis.c index 985eff7..1181e6d 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -9,12 +9,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. -// -// No warranty for any purpose is expressed or implied by the author (nor -// by RAD Game Tools). Report bugs and send enhancements to the author. +// See end of file for license information. // // Limitations: // @@ -5407,3 +5402,46 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in */ #endif // STB_VORBIS_HEADER_ONLY + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stb_voxel_render.h b/stb_voxel_render.h index c49aa40..30dd42f 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -217,9 +217,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. #ifndef INCLUDE_STB_VOXEL_RENDER_H #define INCLUDE_STB_VOXEL_RENDER_H @@ -3750,3 +3748,45 @@ int main(int argc, char **argv) // (v: x:2,y:2,z:2,light:2) #endif // STB_VOXEL_RENDER_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/stretchy_buffer.h b/stretchy_buffer.h index 9b47a67..bb711f6 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -21,7 +21,7 @@ // - the length of the "in-use" part of the array // - the current size of the allocated array // -// I find it to be single most useful non-built-in-structure when +// I find it to be the single most useful non-built-in-structure when // programming in C (hash tables a close second), but to be clear // it lacks many of the capabilities of C++ vector<>: there is no // range checking, the object address isn't stable (see next section @@ -57,7 +57,7 @@ // // 1. can't take long-term pointers to elements of the array // 2. have to return the pointer from functions which might expand it -// (either as a return value or by passing it back) +// (either as a return value or by storing it to a ptr-to-ptr) // // Now you can do the following things with this array: // @@ -164,9 +164,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. #ifndef STB_STRETCHY_BUFFER_H_INCLUDED #define STB_STRETCHY_BUFFER_H_INCLUDED @@ -214,3 +212,46 @@ static void * stb__sbgrowf(void *arr, int increment, int itemsize) } } #endif // STB_STRETCHY_BUFFER_H_INCLUDED + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ From 47685c5f84900b7a70fb7e3a7b6b58b585c852b0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:19:09 -0800 Subject: [PATCH 476/522] remove deprecated old-precision jpg path from stb_image.h tweak license reference wording --- stb_c_lexer.h | 2 +- stb_connected_components.h | 2 +- stb_divide.h | 2 +- stb_dxt.h | 2 +- stb_easy_font.h | 2 +- stb_image.h | 206 +++++++++---------------------------- stb_image_write.h | 61 +++++++++-- 7 files changed, 107 insertions(+), 170 deletions(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index 987984b..e5a909e 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -36,7 +36,7 @@ // // LICENSE // -// See end of file for licensing information. +// See end of file for license information. #ifndef STB_C_LEXER_DEFINITIONS // to change the default parsing rules, copy the following lines diff --git a/stb_connected_components.h b/stb_connected_components.h index 04b28de..4c358fb 100644 --- a/stb_connected_components.h +++ b/stb_connected_components.h @@ -52,7 +52,7 @@ // // LICENSE // -// See end of file for licensing information. +// See end of file for license information. // // ALGORITHM // diff --git a/stb_divide.h b/stb_divide.h index 24d0788..81948ae 100644 --- a/stb_divide.h +++ b/stb_divide.h @@ -78,7 +78,7 @@ // // LICENSE // -// See end of file for licensing information. +// See end of file for license information. #ifndef INCLUDE_STB_DIVIDE_H diff --git a/stb_dxt.h b/stb_dxt.h index c03c8d0..e467c30 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -19,7 +19,7 @@ // // LICENSE // -// See end of file for licensing information. +// See end of file for license information. #ifndef STB_INCLUDE_STB_DXT_H #define STB_INCLUDE_STB_DXT_H diff --git a/stb_easy_font.h b/stb_easy_font.h index 506054f..afe4013 100644 --- a/stb_easy_font.h +++ b/stb_easy_font.h @@ -67,7 +67,7 @@ // // LICENSE // -// See end of file for licensing information. +// See end of file for license information. // // VERSION HISTORY // diff --git a/stb_image.h b/stb_image.h index 83ad9ba..d72d081 100644 --- a/stb_image.h +++ b/stb_image.h @@ -21,7 +21,7 @@ avoid problematic images and only need the trivial interface JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) - PNG 1/2/4/8-bit-per-channel (16 bpc not supported) + PNG 1/2/4/8/16-bit-per-channel TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE @@ -42,110 +42,13 @@ Full documentation under "DOCUMENTATION" below. - Revision 2.00 release notes: +LICENSE - - Progressive JPEG is now supported. + See end of file for license information. - - PPM and PGM binary formats are now supported, thanks to Ken Miller. +RECENT REVISION HISTORY: - - x86 platforms now make use of SSE2 SIMD instructions for - JPEG decoding, and ARM platforms can use NEON SIMD if requested. - This work was done by Fabian "ryg" Giesen. SSE2 is used by - default, but NEON must be enabled explicitly; see docs. - - With other JPEG optimizations included in this version, we see - 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup - on a JPEG on an ARM machine, relative to previous versions of this - library. The same results will not obtain for all JPGs and for all - x86/ARM machines. (Note that progressive JPEGs are significantly - slower to decode than regular JPEGs.) This doesn't mean that this - is the fastest JPEG decoder in the land; rather, it brings it - closer to parity with standard libraries. If you want the fastest - decode, look elsewhere. (See "Philosophy" section of docs below.) - - See final bullet items below for more info on SIMD. - - - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing - the memory allocator. Unlike other STBI libraries, these macros don't - support a context parameter, so if you need to pass a context in to - the allocator, you'll have to store it in a global or a thread-local - variable. - - - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and - STBI_NO_LINEAR. - STBI_NO_HDR: suppress implementation of .hdr reader format - STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API - - - You can suppress implementation of any of the decoders to reduce - your code footprint by #defining one or more of the following - symbols before creating the implementation. - - STBI_NO_JPEG - STBI_NO_PNG - STBI_NO_BMP - STBI_NO_PSD - STBI_NO_TGA - STBI_NO_GIF - STBI_NO_HDR - STBI_NO_PIC - STBI_NO_PNM (.ppm and .pgm) - - - You can request *only* certain decoders and suppress all other ones - (this will be more forward-compatible, as addition of new decoders - doesn't require you to disable them explicitly): - - STBI_ONLY_JPEG - STBI_ONLY_PNG - STBI_ONLY_BMP - STBI_ONLY_PSD - STBI_ONLY_TGA - STBI_ONLY_GIF - STBI_ONLY_HDR - STBI_ONLY_PIC - STBI_ONLY_PNM (.ppm and .pgm) - - Note that you can define multiples of these, and you will get all - of them ("only x" and "only y" is interpreted to mean "only x&y"). - - - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still - want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB - - - Compilation of all SIMD code can be suppressed with - #define STBI_NO_SIMD - It should not be necessary to disable SIMD unless you have issues - compiling (e.g. using an x86 compiler which doesn't support SSE - intrinsics or that doesn't support the method used to detect - SSE2 support at run-time), and even those can be reported as - bugs so I can refine the built-in compile-time checking to be - smarter. - - - The old STBI_SIMD system which allowed installing a user-defined - IDCT etc. has been removed. If you need this, don't upgrade. My - assumption is that almost nobody was doing this, and those who - were will find the built-in SIMD more satisfactory anyway. - - - RGB values computed for JPEG images are slightly different from - previous versions of stb_image. (This is due to using less - integer precision in SIMD.) The C code has been adjusted so - that the same RGB values will be computed regardless of whether - SIMD support is available, so your app should always produce - consistent results. But these results are slightly different from - previous versions. (Specifically, about 3% of available YCbCr values - will compute different RGB results from pre-1.49 versions by +-1; - most of the deviating values are one smaller in the G channel.) - - - If you must produce consistent results with previous versions of - stb_image, #define STBI_JPEG_OLD and you will get the same results - you used to; however, you will not get the SIMD speedups for - the YCbCr-to-RGB conversion step (although you should still see - significant JPEG speedup from the other changes). - - Please note that STBI_JPEG_OLD is a temporary feature; it will be - removed in future versions of the library. It is only intended for - near-term back-compatibility use. - - - Latest revision history: + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 @@ -194,11 +97,6 @@ Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github Blazej Dariusz Roszkowski github:sammyhw - -LICENSE - - See end of file for licensing information. - */ #ifndef STBI_INCLUDE_STB_IMAGE_H @@ -272,13 +170,13 @@ LICENSE // and for best performance I may provide less-easy-to-use APIs that give higher // performance, in addition to the easy to use ones. Nevertheless, it's important // to keep in mind that from the standpoint of you, a client of this library, -// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all. +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. // // Some secondary priorities arise directly from the first two, some of which // make more explicit reasons why performance can't be emphasized. // // - Portable ("ease of use") -// - Small footprint ("easy to maintain") +// - Small source code footprint ("easy to maintain") // - No dependencies ("ease of use") // // =========================================================================== @@ -310,13 +208,6 @@ LICENSE // (at least this is true for iOS and Android). Therefore, the NEON support is // toggled by a build flag: define STBI_NEON to get NEON loops. // -// The output of the JPEG decoder is slightly different from versions where -// SIMD support was introduced (that is, for versions before 1.49). The -// difference is only +-1 in the 8-bit RGB channels, and only on a small -// fraction of pixels. You can force the pre-1.49 behavior by defining -// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path -// and hence cost some performance. -// // If for some reason you do not want to use any of SIMD code, or if // you have issues compiling it, you can disable it entirely by // defining STBI_NO_SIMD. @@ -372,6 +263,41 @@ LICENSE // says there's premultiplied data (currently only happens in iPhone images, // and only if iPhone convert-to-rgb processing is on). // +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// #ifndef STBI_NO_STDIO @@ -3345,38 +3271,9 @@ static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_ return out; } -#ifdef STBI_JPEG_OLD -// this is the same YCbCr-to-RGB calculation that stb_image has used -// historically before the algorithm changes in 1.49 -#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) -static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) -{ - int i; - for (i=0; i < count; ++i) { - int y_fixed = (y[i] << 16) + 32768; // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr*float2fixed(1.40200f); - g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); - b = y_fixed + cb*float2fixed(1.77200f); - r >>= 16; - g >>= 16; - b >>= 16; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#else // this is a reduced-precision calculation of YCbCr-to-RGB introduced // to make sure the code produces the same results in both SIMD and scalar -#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) { int i; @@ -3385,9 +3282,9 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; @@ -3401,7 +3298,6 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc out += step; } } -#endif #if defined(STBI_SSE2) || defined(STBI_NEON) static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) @@ -3520,9 +3416,9 @@ static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc cons int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; @@ -3548,18 +3444,14 @@ static void stbi__setup_jpeg(stbi__jpeg *j) #ifdef STBI_SSE2 if (stbi__sse2_available()) { j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; } #endif #ifdef STBI_NEON j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; #endif } diff --git a/stb_image_write.h b/stb_image_write.h index fdc01e4..df62339 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.03 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.05 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -104,12 +104,11 @@ CREDITS: Filip Wasil Thatcher Ulrich github:poppolopoppo + Patrick Boettcher LICENSE -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish, and distribute this file as you see fit. + See end of file for license information. */ @@ -294,8 +293,8 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in s->func(s->context, &d[comp - 1], 1); switch (comp) { - case 1: /* fall-through wanted */ - case 2: + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: if (expand_mono) stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp else @@ -895,6 +894,7 @@ static unsigned char stbiw__paeth(int a, int b, int c) return STBIW_UCHAR(c); } +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) { int ctype[5] = { -1, 0, 4, 2, 6 }; @@ -911,10 +911,10 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in for (j=0; j < y; ++j) { static int mapping[] = { 0,1,2,3,4 }; static int firstmap[] = { 0,1,0,5,6 }; - int *mymap = j ? mapping : firstmap; + int *mymap = (j != 0) ? mapping : firstmap; int best = 0, bestval = 0x7fffffff; for (p=0; p < 2; ++p) { - for (k= p?best:0; k < 5; ++k) { + for (k= p?best:0; k < 5; ++k) { // @TODO: clarity: rewrite this to go 0..5, and 'continue' the unwanted ones during 2nd pass int type = mymap[k],est=0; unsigned char *z = pixels + stride_bytes*j; for (i=0; i < n; ++i) @@ -1016,6 +1016,9 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? 1.02 (2016-04-02) avoid allocating large structures on the stack 1.01 (2016-01-16) @@ -1045,3 +1048,45 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, first public release 0.90 first internal release */ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ From 786ac92daaac10307d3116e1c12ed454d398a69f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:30:49 -0800 Subject: [PATCH 477/522] tweak RGB-to-Y conversion --- stb_image.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/stb_image.h b/stb_image.h index 199e06e..06b4ec8 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 @@ -78,6 +78,7 @@ RECENT REVISION HISTORY: github:urraka (animated gif) Junggon Kim (PNM comments) Daniel Gibson (16-bit TGA) socks-the-fox (16-bit TGA) + Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Fabian "ryg" Giesen Arseny Kapoulkine @@ -95,7 +96,7 @@ RECENT REVISION HISTORY: Ryamond Barbiero Paul Du Bois Engin Manap github:snagar Michaelangel007@github Oriol Ferrer Mesia Dale Weiler github:Zelex Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github - Blazej Dariusz Roszkowski github:sammyhw Jeremy Sawicki + Blazej Dariusz Roszkowski github:sammyhw */ @@ -3565,10 +3566,14 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } } else { if (z->rgb == 3) { - for (i=0; i < z->s->img_x; ++i) { - out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); - out[1] = 255; - out += n; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } } } else { stbi_uc *y = coutput[0]; From a6dc061137a4dbd5c83fbcb355cd854add1154ce Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:35:14 -0800 Subject: [PATCH 478/522] tweak 16-bit quantization for clarity --- stb_image.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index a47767a..1818e44 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2798,13 +2798,14 @@ static int stbi__process_marker(stbi__jpeg *z, int m) L = stbi__get16be(z->s)-2; while (L > 0) { int q = stbi__get8(z->s); - int p = q >> 4; + int p = q >> 4, sixteen = (p != 0); int t = q & 15,i; if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = p == 0 ? stbi__get8(z->s) : stbi__get16be(z->s); - L -= p == 0 ? 65 : 129; + z->dequant[t][stbi__jpeg_dezigzag[i]] = sixteen ? stbi__get16be(z->s) : stbi__get8(z->s); + L -= (sixteen ? 129 : 65); } return L==0; From dc6089f05bc04915dca6801aa49dd6bef997b68a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:37:30 -0800 Subject: [PATCH 479/522] tweak fill byte PR --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 9386aa6..4f705bb 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1776,7 +1776,7 @@ static void stbi__grow_buffer_unsafe(stbi__jpeg *j) int b = j->nomore ? 0 : stbi__get8(j->s); if (b == 0xff) { int c = stbi__get8(j->s); - while (c == 0xff) c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; @@ -2610,7 +2610,7 @@ static stbi_uc stbi__get_marker(stbi__jpeg *j) x = stbi__get8(j->s); if (x != 0xff) return STBI__MARKER_none; while (x == 0xff) - x = stbi__get8(j->s); + x = stbi__get8(j->s); // consume repeated 0xff fill bytes return x; } From 8879908f7879c2526533323bc85130142e87677d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:41:01 -0800 Subject: [PATCH 480/522] update readme --- README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index c22b270..bc7a643 100644 --- a/README.md +++ b/README.md @@ -11,29 +11,29 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**[stb_vorbis.c](stb_vorbis.c)** | 1.09 | audio | 5399 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.14 | graphics | 7102 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.14 | graphics | 4018 | parse, decode, and rasterize characters from truetype fonts -**[stb_image_write.h](stb_image_write.h)** | 1.03 | graphics | 1049 | image writing to disk: PNG, TGA, BMP -**[stb_image_resize.h](stb_image_resize.h)** | 0.92 | graphics | 2580 | resize images larger/smaller with good quality -**[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 583 | simple 2D rectangle packer with decent quality -**[stb_sprintf.h](stb_sprintf.h)** | 1.02 | utility | 1087 | fast sprintf, snprintf for C/C++ -**[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 216 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1330 | guts of a text editor for games etc implementing them from scratch -**[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3752 | Minecraft-esque voxel rendering "engine" with many more features -**[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 630 | Fabian "ryg" Giesen's real-time DXT compressor -**[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 182 | revised Perlin noise (3D input, 1D output) -**[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D graphics | 263 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc -**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.38 | game dev | 4132 | embeddable tilemap editor +**[stb_vorbis.c](stb_vorbis.c)** | 1.10 | audio | 5447 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_image.h](stb_image.h)** | 2.14 | graphics | 7049 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.14 | graphics | 4058 | parse, decode, and rasterize characters from truetype fonts +**[stb_image_write.h](stb_image_write.h)** | 1.05 | graphics | 1092 | image writing to disk: PNG, TGA, BMP +**[stb_image_resize.h](stb_image_resize.h)** | 0.92 | graphics | 2620 | resize images larger/smaller with good quality +**[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 623 | simple 2D rectangle packer with decent quality +**[stb_sprintf.h](stb_sprintf.h)** | 1.02 | utility | 1134 | fast sprintf, snprintf for C/C++ +**[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 257 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ +**[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1370 | guts of a text editor for games etc implementing them from scratch +**[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3792 | Minecraft-esque voxel rendering "engine" with many more features +**[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 669 | Fabian "ryg" Giesen's real-time DXT compressor +**[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 222 | revised Perlin noise (3D input, 1D output) +**[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D graphics | 303 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc +**[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.38 | game dev | 4172 | embeddable tilemap editor **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.6 | game dev | 1220 | herringbone Wang tile map generator -**[stb_c_lexer.h](stb_c_lexer.h)** | 0.08 | parsing | 820 | simplify writing parsers for C-like languages -**[stb_divide.h](stb_divide.h)** | 0.91 | math | 379 | more useful 32-bit modulus e.g. "euclidean divide" -**[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1006 | incrementally compute reachability on grids +**[stb_c_lexer.h](stb_c_lexer.h)** | 0.08 | parsing | 859 | simplify writing parsers for C-like languages +**[stb_divide.h](stb_divide.h)** | 0.91 | math | 419 | more useful 32-bit modulus e.g. "euclidean divide" +**[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1045 | incrementally compute reachability on grids **[stb.h](stb.h)** | 2.28 | misc | 14277 | helper functions for C, mostly redundant in C++; basically author's personal stuff -**[stb_leakcheck.h](stb_leakcheck.h)** | 0.3 | misc | 124 | quick-and-dirty malloc/free leak-checking +**[stb_leakcheck.h](stb_leakcheck.h)** | 0.3 | misc | 165 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 50149 +Total lines of C code: 50793 FAQ From a217948c16b939b1491ae1776da5440c9230d1fa Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:49:08 -0800 Subject: [PATCH 481/522] change 3dc name to bc5 --- stb_dxt.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index ebe445c..2bc5831 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -1,4 +1,4 @@ -// stb_dxt.h - v1.04 - DXT1/DXT5 compressor - public domain +// stb_dxt.h - v1.05 - DXT1/DXT5 compressor - public domain // original by fabian "ryg" giesen - ported to C by stb // use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation // @@ -9,6 +9,7 @@ // and "high quality" using mode. // // version history: +// v1.05 - (stb) support bc5/3dc (Arvids Kokins) // v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec); // single color match fix (allow for inexact color interpolation); // optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps. @@ -30,7 +31,7 @@ #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower. void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode); -void stb_compress_3dc_block_rgxx8(unsigned char *dest, const unsigned char *src, int mode); +void stb_compress_bc5_block_rg88(unsigned char *dest, const unsigned char *src, int mode); #define STB_COMPRESS_DXT_BLOCK #ifdef STB_DXT_IMPLEMENTATION @@ -537,7 +538,7 @@ static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, i } // Alpha block compression (this is easy for a change) -static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src,int mode) +static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int stride) { int i,dist,bias,dist4,dist2,bits,mask; @@ -567,7 +568,7 @@ static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src,int m bits = 0,mask=0; for (i=0;i<16;i++) { - int a = src[i*4+3]*7 + bias; + int a = src[i*stride]*7 + bias; int ind,t; // select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max). @@ -618,17 +619,17 @@ void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int a } if (alpha) { - stb__CompressAlphaBlock(dest,(unsigned char*) src,mode); + stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4); dest += 8; } stb__CompressColorBlock(dest,(unsigned char*) src,mode); } -void stb_compress_3dc_block_rgxx8(unsigned char *dest, const unsigned char *src, int mode) +void stb_compress_bc5_block_rg88(unsigned char *dest, const unsigned char *src) { - stb__CompressAlphaBlock(dest,(unsigned char*) src - 3,mode); - stb__CompressAlphaBlock(dest + 8,(unsigned char*) src - 2,mode); + stb__CompressAlphaBlock(dest,(unsigned char*) src,2); + stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2); } #endif // STB_DXT_IMPLEMENTATION #endif // STB_INCLUDE_STB_DXT_H From 4ce23da44aeca01bc70a87b4913bd986383f05c9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:54:44 -0800 Subject: [PATCH 482/522] rename 3dc to bc5, tweaks to clean stuff up --- stb_dxt.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index 2bc5831..bcf44b8 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -30,8 +30,8 @@ #define STB_DXT_DITHER 1 // use dithering. dubious win. never use for normal maps and the like! #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower. -void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode); -void stb_compress_bc5_block_rg88(unsigned char *dest, const unsigned char *src, int mode); +void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); +void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel, int mode); #define STB_COMPRESS_DXT_BLOCK #ifdef STB_DXT_IMPLEMENTATION @@ -626,7 +626,7 @@ void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int a stb__CompressColorBlock(dest,(unsigned char*) src,mode); } -void stb_compress_bc5_block_rg88(unsigned char *dest, const unsigned char *src) +void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src) { stb__CompressAlphaBlock(dest,(unsigned char*) src,2); stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2); From 6ba52a370c27e024bb451f2f28ad3f58c4007190 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:57:34 -0800 Subject: [PATCH 483/522] stb_dxt: extern "C" --- stb_dxt.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/stb_dxt.h b/stb_dxt.h index bcf44b8..55384bd 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -9,7 +9,7 @@ // and "high quality" using mode. // // version history: -// v1.05 - (stb) support bc5/3dc (Arvids Kokins) +// v1.05 - (stb) support bc5/3dc (Arvids Kokins), use extern "C" in C++ (Pavel Krajcevski) // v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec); // single color match fix (allow for inexact color interpolation); // optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps. @@ -30,8 +30,17 @@ #define STB_DXT_DITHER 1 // use dithering. dubious win. never use for normal maps and the like! #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower. +#ifdef __cplusplus +extern "C" { +#endif + void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel, int mode); + +#ifdef __cplusplus +} +#endif + #define STB_COMPRESS_DXT_BLOCK #ifdef STB_DXT_IMPLEMENTATION From 2d0518833b3df0881d8d9549fad8fd0f81fd0f51 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 08:59:52 -0800 Subject: [PATCH 484/522] readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bc7a643..6f789b4 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ library | lastest version | category | LoC | description **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 257 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1370 | guts of a text editor for games etc implementing them from scratch **[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3792 | Minecraft-esque voxel rendering "engine" with many more features -**[stb_dxt.h](stb_dxt.h)** | 1.04 | 3D graphics | 669 | Fabian "ryg" Giesen's real-time DXT compressor +**[stb_dxt.h](stb_dxt.h)** | 1.05 | 3D graphics | 686 | Fabian "ryg" Giesen's real-time DXT compressor **[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 222 | revised Perlin noise (3D input, 1D output) **[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D graphics | 303 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.38 | game dev | 4172 | embeddable tilemap editor @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.3 | misc | 165 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 50793 +Total lines of C code: 50810 FAQ From 83a2489d5b3104c4ea67cd003c8cfd10a2493d5d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 09:22:07 -0800 Subject: [PATCH 485/522] fix compilation on non-C99 compilers --- stb_c_lexer.h | 26 +++++++++++++----------- tests/c_lexer_test.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index bec0272..95d37dc 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -727,18 +727,20 @@ int stb_c_lexer_get_token(stb_lexer *lexer) #ifdef STB__CLEX_use_stdlib lexer->int_number = strtol((char *) p, (char **) &q, 16); #else - stb__clex_int n=0; - for (q=p+2; q != lexer->eof; ++q) { - if (*q >= '0' && *q <= '9') - n = n*16 + (*q - '0'); - else if (*q >= 'a' && *q <= 'f') - n = n*16 + (*q - 'a') + 10; - else if (*q >= 'A' && *q <= 'F') - n = n*16 + (*q - 'A') + 10; - else - break; + { + stb__clex_int n=0; + for (q=p+2; q != lexer->eof; ++q) { + if (*q >= '0' && *q <= '9') + n = n*16 + (*q - '0'); + else if (*q >= 'a' && *q <= 'f') + n = n*16 + (*q - 'a') + 10; + else if (*q >= 'A' && *q <= 'F') + n = n*16 + (*q - 'A') + 10; + else + break; + } + lexer->int_number = n; } - lexer->int_number = n; #endif if (q == p+2) return stb__clex_token(lexer, CLEX_parse_error, p-2,p-1); @@ -880,7 +882,7 @@ void dummy(void) { double some_floats[] = { 1.0501, -10.4e12, 5E+10, -#ifdef STB__clex_hex_floats +#if 0 // not support in C++ or C-pre-99, so don't try to compile it 0x1.0p+24, 0xff.FP-8, 0x1p-23, #endif 4. diff --git a/tests/c_lexer_test.c b/tests/c_lexer_test.c index fda7d75..a919b6c 100644 --- a/tests/c_lexer_test.c +++ b/tests/c_lexer_test.c @@ -1,3 +1,50 @@ +#define STB_C_LEX_C_DECIMAL_INTS Y // "0|[1-9][0-9]*" CLEX_intlit +#define STB_C_LEX_C_HEX_INTS Y // "0x[0-9a-fA-F]+" CLEX_intlit +#define STB_C_LEX_C_OCTAL_INTS Y // "[0-7]+" CLEX_intlit +#define STB_C_LEX_C_DECIMAL_FLOATS Y // "[0-9]*(.[0-9]*([eE][-+]?[0-9]+)?) CLEX_floatlit +#define STB_C_LEX_C99_HEX_FLOATS Y // "0x{hex}+(.{hex}*)?[pP][-+]?{hex}+ CLEX_floatlit +#define STB_C_LEX_C_IDENTIFIERS Y // "[_a-zA-Z][_a-zA-Z0-9]*" CLEX_id +#define STB_C_LEX_C_DQ_STRINGS Y // double-quote-delimited strings with escapes CLEX_dqstring +#define STB_C_LEX_C_SQ_STRINGS Y // single-quote-delimited strings with escapes CLEX_ssstring +#define STB_C_LEX_C_CHARS Y // single-quote-delimited character with escape CLEX_charlits +#define STB_C_LEX_C_COMMENTS Y // "/* comment */" +#define STB_C_LEX_CPP_COMMENTS Y // "// comment to end of line\n" +#define STB_C_LEX_C_COMPARISONS Y // "==" CLEX_eq "!=" CLEX_noteq "<=" CLEX_lesseq ">=" CLEX_greatereq +#define STB_C_LEX_C_LOGICAL Y // "&&" CLEX_andand "||" CLEX_oror +#define STB_C_LEX_C_SHIFTS Y // "<<" CLEX_shl ">>" CLEX_shr +#define STB_C_LEX_C_INCREMENTS Y // "++" CLEX_plusplus "--" CLEX_minusminus +#define STB_C_LEX_C_ARROW Y // "->" CLEX_arrow +#define STB_C_LEX_EQUAL_ARROW Y // "=>" CLEX_eqarrow +#define STB_C_LEX_C_BITWISEEQ Y // "&=" CLEX_andeq "|=" CLEX_oreq "^=" CLEX_xoreq +#define STB_C_LEX_C_ARITHEQ Y // "+=" CLEX_pluseq "-=" CLEX_minuseq + // "*=" CLEX_muleq "/=" CLEX_diveq "%=" CLEX_modeq + // if both STB_C_LEX_SHIFTS & STB_C_LEX_ARITHEQ: + // "<<=" CLEX_shleq ">>=" CLEX_shreq + +#define STB_C_LEX_PARSE_SUFFIXES Y // letters after numbers are parsed as part of those numbers, and must be in suffix list below +#define STB_C_LEX_DECIMAL_SUFFIXES "uUlL" // decimal integer suffixes e.g. "uUlL" -- these are returned as-is in string storage +#define STB_C_LEX_HEX_SUFFIXES "lL" // e.g. "uUlL" +#define STB_C_LEX_OCTAL_SUFFIXES "lL" // e.g. "uUlL" +#define STB_C_LEX_FLOAT_SUFFIXES "uulL" // + +#define STB_C_LEX_0_IS_EOF N // if Y, ends parsing at '\0'; if N, returns '\0' as token +#define STB_C_LEX_INTEGERS_AS_DOUBLES N // parses integers as doubles so they can be larger than 'int', but only if STB_C_LEX_STDLIB==N +#define STB_C_LEX_MULTILINE_DSTRINGS Y // allow newlines in double-quoted strings +#define STB_C_LEX_MULTILINE_SSTRINGS Y // allow newlines in single-quoted strings +#define STB_C_LEX_USE_STDLIB N // use strtod,strtol for parsing #s; otherwise inaccurate hack +#define STB_C_LEX_DOLLAR_IDENTIFIER Y // allow $ as an identifier character +#define STB_C_LEX_FLOAT_NO_DECIMAL Y // allow floats that have no decimal point if they have an exponent + +#define STB_C_LEX_DEFINE_ALL_TOKEN_NAMES Y // if Y, all CLEX_ token names are defined, even if never returned + // leaving it as N should help you catch config bugs + +#define STB_C_LEX_DISCARD_PREPROCESSOR Y // discard C-preprocessor directives (e.g. after prepocess + // still have #line, #pragma, etc) + +#define STB_C_LEXER_DEFINITIONS // This line prevents the header file from replacing your definitions + + + #define STB_C_LEXER_IMPLEMENTATION #define STB_C_LEXER_SELF_TEST #include "../stb_c_lexer.h" From 3afc3de41da4ccd917e5079f4b1271c6c25c587b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 09:31:25 -0800 Subject: [PATCH 486/522] version number --- stb_c_lexer.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_c_lexer.h b/stb_c_lexer.h index 95d37dc..b587ca7 100644 --- a/stb_c_lexer.h +++ b/stb_c_lexer.h @@ -1,4 +1,4 @@ -// stb_c_lexer.h - v0.08 - public domain Sean Barrett 2013 +// stb_c_lexer.h - v0.09 - public domain Sean Barrett 2013 // lexer for making little C-like languages with recursive-descent parsers // // This file provides both the interface and the implementation. @@ -10,6 +10,7 @@ // suffixes on integer constants are not handled (you can override this). // // History: +// 0.09 hex floats, no-stdlib fixes // 0.08 fix bad pointer comparison // 0.07 fix mishandling of hexadecimal constants parsed by strtol // 0.06 fix missing next character after ending quote mark (Andreas Fredriksson) @@ -33,6 +34,7 @@ // // Contributors: // Arpad Goretity (bugfix) +// Alan Hickman (hex floats) // // LICENSE // From 0c1232f576e9fb92586bb983f03e8b7c8b2c1b2a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 09:37:50 -0800 Subject: [PATCH 487/522] version number --- stb_truetype.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 4b41e0d..fc5b978 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.14 - public domain +// stb_truetype.h - v1.15 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -54,7 +54,9 @@ // // VERSION HISTORY // -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts, num-fonts-in-TTC function +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef From d79487a0ba7d959135b28feee934e69688295f64 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 09:38:25 -0800 Subject: [PATCH 488/522] readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6f789b4..4197a8c 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.10 | audio | 5447 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_image.h](stb_image.h)** | 2.14 | graphics | 7049 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.14 | graphics | 4058 | parse, decode, and rasterize characters from truetype fonts +**[stb_truetype.h](stb_truetype.h)** | 1.15 | graphics | 4061 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.05 | graphics | 1092 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.92 | graphics | 2620 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 623 | simple 2D rectangle packer with decent quality @@ -26,14 +26,14 @@ library | lastest version | category | LoC | description **[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D graphics | 303 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.38 | game dev | 4172 | embeddable tilemap editor **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.6 | game dev | 1220 | herringbone Wang tile map generator -**[stb_c_lexer.h](stb_c_lexer.h)** | 0.08 | parsing | 859 | simplify writing parsers for C-like languages +**[stb_c_lexer.h](stb_c_lexer.h)** | 0.09 | parsing | 962 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.91 | math | 419 | more useful 32-bit modulus e.g. "euclidean divide" **[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1045 | incrementally compute reachability on grids **[stb.h](stb.h)** | 2.28 | misc | 14277 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.3 | misc | 165 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 50810 +Total lines of C code: 50916 FAQ From fd912b5d936c98b6087c768d4473662803b4590b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 09:52:42 -0800 Subject: [PATCH 489/522] version number, doc tweaks --- stb_voxel_render.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 8469464..514ed99 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -1,4 +1,4 @@ -// stb_voxel_render.h - v0.84 - Sean Barrett, 2015 - public domain +// stb_voxel_render.h - v0.85 - Sean Barrett, 2015 - public domain // // This library helps render large-scale "voxel" worlds for games, // in this case, one with blocks that can have textures and that @@ -13,7 +13,7 @@ // It works by creating triangle meshes. The library includes // // - converter from dense 3D arrays of block info to vertex mesh -// - shader for the vertex mesh +// - vertex & fragment shaders for the vertex mesh // - assistance in setting up shader state // // For portability, none of the library code actually accesses @@ -24,8 +24,9 @@ // yourself. However, you could also try making a game with // a small enough world that it's fully loaded rather than // streaming. Currently the preferred vertex format is 20 bytes -// per quad. There are plans to allow much more compact formats -// with a slight reduction in shader features. +// per quad. There are designs to allow much more compact formats +// with a slight reduction in shader features, but no roadmap +// for actually implementing them. // // // USAGE @@ -108,7 +109,7 @@ // and avoids a potential slow path (gathering non-uniform // data from uniforms) on some hardware. // -// In the future I hope to add additional modes that have significantly +// In the future I might add additional modes that have significantly // smaller meshes but reduce features, down as small as 6 bytes per quad. // See elsewhere in this file for a table of candidate modes. Switching // to a mode will require changing some of your mesh creation code, but @@ -187,10 +188,11 @@ // Sean Barrett github:r-leyh Jesus Fernandez // Miguel Lechon github:Arbeiterunfallversicherungsgesetz // Thomas Frase James Hofmann -// Stephen Olsen +// Stephen Olsen github:guitarfreak // // VERSION HISTORY // +// 0.85 (2017-03-03) add block_selector (by guitarfreak) // 0.84 (2016-04-02) fix GLSL syntax error on glModelView path // 0.83 (2015-09-13) remove non-constant struct initializers to support more compilers // 0.82 (2015-08-01) added input.packed_compact to store rot, vheight & texlerp efficiently @@ -262,7 +264,7 @@ extern "C" { // modes 0,1,20,21, Z in the mesh can extend to 511 instead // of 255. However, half-height blocks cannot be used. // -// All of the following just #ifdef tested so need no values, and are optional. +// All of the following are just #ifdef tested so need no values, and are optional. // // STBVOX_CONFIG_BLOCKTYPE_SHORT // use unsigned 16-bit values for 'blocktype' in the input instead of 8-bit values @@ -302,7 +304,7 @@ extern "C" { // // STBVOX_CONFIG_DISABLE_TEX2 // This disables all processing of texture 2 in the shader in case -// you don't use it. Eventually this will be replaced with a mode +// you don't use it. Eventually this could be replaced with a mode // that omits the unused data entirely. // // STBVOX_CONFIG_TEX1_EDGE_CLAMP From 324be64e8082384aca1f3ef305075bb647ae4cdf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 09:57:09 -0800 Subject: [PATCH 490/522] version number --- stb_sprintf.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_sprintf.h b/stb_sprintf.h index 3283156..ad5d9bc 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -8,6 +8,7 @@ // Contributors (bugfixes): // github:d26435 // github:trex78 +// Jari Komppa (SI suffixes) // // LICENSE: // From c918a6b801e6d2c4720c5fc5fd54720a5cc1999f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:02:54 -0800 Subject: [PATCH 491/522] tweak previous PR merge --- stb_sprintf.h | 55 +++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index e254e0f..0ed30a0 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -226,6 +226,35 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE( set_separators )( char pcomma, char stbsp__comma=pcomma; } +#define STBSP__LEFTJUST 1 +#define STBSP__LEADINGPLUS 2 +#define STBSP__LEADINGSPACE 4 +#define STBSP__LEADING_0X 8 +#define STBSP__LEADINGZERO 16 +#define STBSP__INTMAX 32 +#define STBSP__TRIPLET_COMMA 64 +#define STBSP__NEGATIVE 128 +#define STBSP__METRIC_SUFFIX 256 +#define STBSP__HALFWIDTH 512 +#define STBSP__METRIC_NOSPACE 1024 +#define STBSP__METRIC_1024 2048 +#define STBSP__METRIC_JEDEC 4096 + +static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) +{ + sign[0] = 0; + if (fl&STBSP__NEGATIVE) { + sign[0]=1; + sign[1]='-'; + } else if (fl&STBSP__LEADINGSPACE) { + sign[0]=1; + sign[1]=' '; + } else if (fl&STBSP__LEADINGPLUS) { + sign[0]=1; + sign[1]='+'; + } +} + STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) { static char hex[]="0123456789abcdefxp"; @@ -240,37 +269,11 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsprintfcb )( STBSP_SPRINTFCB * callb { stbsp__int32 fw,pr,tz; stbsp__uint32 fl; - #define STBSP__LEFTJUST 1 - #define STBSP__LEADINGPLUS 2 - #define STBSP__LEADINGSPACE 4 - #define STBSP__LEADING_0X 8 - #define STBSP__LEADINGZERO 16 - #define STBSP__INTMAX 32 - #define STBSP__TRIPLET_COMMA 64 - #define STBSP__NEGATIVE 128 - #define STBSP__METRIC_SUFFIX 256 - #define STBSP__HALFWIDTH 512 - #define STBSP__METRIC_NOSPACE 1024 - #define STBSP__METRIC_1024 2048 - #define STBSP__METRIC_JEDEC 4096 - // macros for the callback buffer stuff #define stbsp__chk_cb_bufL(bytes) { int len = (int)(bf-buf); if ((len+(bytes))>=STB_SPRINTF_MIN) { tlen+=len; if (0==(bf=buf=callback(buf,user,len))) goto done; } } #define stbsp__chk_cb_buf(bytes) { if ( callback ) { stbsp__chk_cb_bufL(bytes); } } #define stbsp__flush_cb() { stbsp__chk_cb_bufL(STB_SPRINTF_MIN-1); } //flush if there is even one byte in the buffer #define stbsp__cb_buf_clamp(cl,v) cl = v; if ( callback ) { int lg = STB_SPRINTF_MIN-(int)(bf-buf); if (cl>lg) cl=lg; } - #define stbsp__lead_sign(fl, lead) \ - lead[0] = 0;\ - if (fl&STBSP__NEGATIVE) {\ - lead[0]=1;\ - lead[1]='-';\ - } else if (fl&STBSP__LEADINGSPACE) {\ - lead[0]=1;\ - lead[1]=' ';\ - } else if (fl&STBSP__LEADINGPLUS) {\ - lead[0]=1;\ - lead[1]='+';\ - } // fast copy everything up to the next % (or end of string) for(;;) From e895f6d3afd840ff29bfbac0d3917fe6ce32a5fc Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:07:16 -0800 Subject: [PATCH 492/522] tweak previous PR merge --- stb_rect_pack.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index 865cd40..f5eb8d3 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.10 - public domain - rectangle packing +// stb_rect_pack.h - v0.11 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -27,11 +27,14 @@ // Sean Barrett // Minor features // Martins Mozeiko +// github:IntellectualKitty +// // Bugfixes / warning fixes // Jeremy Jaussaud // // Version history: // +// 0.11 (2017-03-03) return packing success/fail result // 0.10 (2016-10-25) remove cast-away-const to avoid warnings // 0.09 (2016-08-27) fix compiler warnings // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) @@ -578,9 +581,9 @@ STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int nu STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); // set was_packed flags and all_rects_packed status - for (i=0; i < num_rects; ++i) - { - if (!(rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL))) + for (i=0; i < num_rects; ++i) { + rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + if (!rects[i].was_packed) all_rects_packed = 0; } From a2bc1eabec827e47c669159e635326fa34c50e0f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:37:20 -0800 Subject: [PATCH 493/522] perlin noise function pull request by Jack Mott but deleted before I could pull it --- stb_perlin.h | 118 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 12 deletions(-) diff --git a/stb_perlin.h b/stb_perlin.h index fa144b2..5d76222 100644 --- a/stb_perlin.h +++ b/stb_perlin.h @@ -1,4 +1,4 @@ -// stb_perlin.h - v0.2 - perlin noise +// stb_perlin.h - v0.3 - perlin noise // public domain single-file C implementation by Sean Barrett // // LICENSE @@ -9,8 +9,8 @@ // to create the implementation, // #define STB_PERLIN_IMPLEMENTATION // in *one* C/CPP file that includes this file. - - +// +// // Documentation: // // float stb_perlin_noise3( float x, @@ -31,22 +31,55 @@ // 0 to mean "don't care". (The noise always wraps every 256 due // details of the implementation, even if you ask for larger or no // wrapping.) +// +// Fractal Noise: +// +// Three common fractal noise functions are included, which produce +// a wide variety of nice effects depending on the parameters +// provided. Note that each function will call stb_perlin_noise3 +// 'octaves' times, so this parameter will affect runtime. +// +// float stb_perlin_ridge_noise3(float x, float y, float z, +// float lacunarity, float gain, float offset, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_fbm_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_turbulence_noise3(float x, float y, float z, +// float lacunarity, float gain,int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// Typical values to start playing with: +// octaves = 6 -- number of "octaves" of noise3() to sum +// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) +// gain = 0.5 -- relative weighting applied to each successive octave +// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure +// +// +// Contributors: +// Jack Mott - additional noise functions +// #ifdef __cplusplus -extern "C" float stb_perlin_noise3(float x, float y, float z, int x_wrap=0, int y_wrap=0, int z_wrap=0); -#else +extern "C" { +#endif extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +#ifdef __cplusplus +} #endif #ifdef STB_PERLIN_IMPLEMENTATION -#include // floor() - // not same permutation table as Perlin's reference to avoid copyright issues; // Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ // @OPTIMIZE: should this be unsigned char instead of int for cache? -static int stb__perlin_randtab[512] = +static unsigned char stb__perlin_randtab[512] = { 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, @@ -89,6 +122,12 @@ static float stb__perlin_lerp(float a, float b, float t) return a + (b-a) * t; } +static int stb__perlin_fastfloor(float a) +{ + int ai = (int) a; + return (a < ai) ? ai-1 : ai; +} + // different grad function from Perlin's, but easy to modify to match reference static float stb__perlin_grad(int hash, float x, float y, float z) { @@ -110,7 +149,7 @@ static float stb__perlin_grad(int hash, float x, float y, float z) // perlin's gradient has 12 cases so some get used 1/16th of the time // and some 2/16ths. We reduce bias by changing those fractions - // to 5/16ths and 6/16ths, and the same 4 cases get the extra weight. + // to 5/64ths and 6/64ths, and the same 4 cases get the extra weight. static unsigned char indices[64] = { 0,1,2,3,4,5,6,7,8,9,10,11, @@ -122,6 +161,7 @@ static float stb__perlin_grad(int hash, float x, float y, float z) }; // if you use reference permutation table, change 63 below to 15 to match reference + // (this is why the ordering of the table above is funky) float *grad = basis[indices[hash & 63]]; return grad[0]*x + grad[1]*y + grad[2]*z; } @@ -136,9 +176,9 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z unsigned int x_mask = (x_wrap-1) & 255; unsigned int y_mask = (y_wrap-1) & 255; unsigned int z_mask = (z_wrap-1) & 255; - int px = (int) floor(x); - int py = (int) floor(y); - int pz = (int) floor(z); + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); int x0 = px & x_mask, x1 = (px+1) & x_mask; int y0 = py & y_mask, y1 = (py+1) & y_mask; int z0 = pz & z_mask, z1 = (pz+1) & z_mask; @@ -177,6 +217,60 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z return stb__perlin_lerp(n0,n1,u); } + +float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float prev = 1.0f; + float amplitude = 0.5f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)); + r = r<0 ? -r : r; // fabs() + r = offset - r; + r = r*r; + sum += r*amplitude*prev; + prev = r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + r = r<0 ? -r : r; // fabs() + sum += r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + #endif // STB_PERLIN_IMPLEMENTATION /* From a81422cd802622051a5305d48f526c68f08d99a8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:41:11 -0800 Subject: [PATCH 494/522] version number --- stb_image_resize.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 9b8fb2e..87bbd11 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1,4 +1,4 @@ -/* stb_image_resize - v0.92 - public domain image resizing +/* stb_image_resize - v0.93 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb @@ -157,6 +157,7 @@ Aras Pranckevicius: bugfix REVISIONS + 0.93 (2017-03-03) fixed bug with certain combinations of heights 0.92 (2017-01-02) fix integer overflow on large (>2GB) images 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions 0.90 (2014-09-17) first released version From b1a0089c4bf7c7012a918550d7dd078b3e674ba1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:45:59 -0800 Subject: [PATCH 495/522] stb.h swprintf fix --- stb.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/stb.h b/stb.h index 4b2933c..edd2e1b 100644 --- a/stb.h +++ b/stb.h @@ -1,4 +1,4 @@ -/* stb.h - v2.28 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h +/* stb.h - v2.29 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h no warranty is offered or implied; use this code at your own risk This is a single header file with a bunch of useful utilities @@ -25,6 +25,7 @@ Version History + 2.29 attempt to fix use of swprintf() 2.28 various new functionality 2.27 test _WIN32 not WIN32 in STB_THREADS 2.26 various warning & bugfixes @@ -173,9 +174,7 @@ Parenthesized items have since been removed. LICENSE -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish, and distribute this file as you see fit. + See end of file for license information. CREDITS @@ -6948,10 +6947,19 @@ static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *acti if (stb__showfile) printf("<"); has_slash = (path[0] && path[strlen(path)-1] == '/'); + + // @TODO: do this concatenation without using swprintf to avoid this mess: +#if defined(_MSC_VER) && _MSC_VER < 1400 if (has_slash) swprintf(full_path, L"%s*", stb__from_utf8(path)); else swprintf(full_path, L"%s/*", stb__from_utf8(path)); +#else + if (has_slash) + swprintf(full_path, 1024, L"%s*", stb__from_utf8(path)); + else + swprintf(full_path, 1024, L"%s/*", stb__from_utf8(path)); +#endif // it's possible this directory is already present: that means it was in the // cache, but its parent wasn't... in that case, we're done with it @@ -14268,10 +14276,49 @@ void stua_run_script(char *s) stua_gc(1); } #endif // STB_DEFINE - #endif // STB_STUA - #undef STB_EXTERN #endif // STB_INCLUDE_STB_H +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ From d052909923d04fa4ff47fdf571e5a57b2d349185 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:57:43 -0800 Subject: [PATCH 496/522] better handle dragging mouse in single-line mode --- stb_textedit.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/stb_textedit.h b/stb_textedit.h index 6740b91..2db20c9 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -441,6 +441,15 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) // API click: on mouse down, move the cursor to the clicked location, and reset the selection static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + state->cursor = stb_text_locate_coord(str, x, y); state->select_start = state->cursor; state->select_end = state->cursor; @@ -450,7 +459,18 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { - int p = stb_text_locate_coord(str, x, y); + int p = 0; + + // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse + // goes off the top or bottom of the text + if( state->single_line ) + { + StbTexteditRow r; + STB_TEXTEDIT_LAYOUTROW(&r, str, 0); + y = r.ymin; + } + + p = stb_text_locate_coord(str, x, y); state->cursor = state->select_end = p; } From def6a1898cbd6dfd6b0f2856f6104cf11ad88c83 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 11:09:36 -0800 Subject: [PATCH 497/522] version number --- stb_textedit.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index cdf3dd7..2fb1179 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// stb_textedit.h - v1.10 - public domain - Sean Barrett +// stb_textedit.h - v1.11 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -17,7 +17,7 @@ // // LICENSE // -// See end of file for license information. +// See end of file for license information. // // // DEPENDENCIES @@ -29,6 +29,7 @@ // // VERSION HISTORY // +// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield // 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual // 1.9 (2016-08-27) customizable move-by-word // 1.8 (2016-04-02) better keyboard handling when mouse button is down @@ -48,12 +49,13 @@ // // Ulf Winklemann: move-by-word in 1.1 // Fabian Giesen: secondary key inputs in 1.5 -// Martins Mozeiko: STB_TEXTEDIT_memmove +// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 // // Bugfixes: // Scott Graham // Daniel Keller // Omar Cornut +// Dan Thompson // // USAGE // From ee19531f68a6626dfb0f3fd8bd09563de8464304 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 11:12:41 -0800 Subject: [PATCH 498/522] fix to new bc5 path --- stb_dxt.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index 55384bd..5399799 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -1,4 +1,4 @@ -// stb_dxt.h - v1.05 - DXT1/DXT5 compressor - public domain +// stb_dxt.h - v1.06 - DXT1/DXT5 compressor - public domain // original by fabian "ryg" giesen - ported to C by stb // use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation // @@ -9,6 +9,7 @@ // and "high quality" using mode. // // version history: +// v1.06 - (stb) fix to known-broken 1.05 // v1.05 - (stb) support bc5/3dc (Arvids Kokins), use extern "C" in C++ (Pavel Krajcevski) // v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec); // single color match fix (allow for inexact color interpolation); @@ -35,7 +36,7 @@ extern "C" { #endif void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); -void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel, int mode); +void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel); #ifdef __cplusplus } @@ -553,12 +554,12 @@ static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int // find min/max color int mn,mx; - mn = mx = src[3]; + mn = mx = src[0]; for (i=1;i<16;i++) { - if (src[i*4+3] < mn) mn = src[i*4+3]; - else if (src[i*4+3] > mx) mx = src[i*4+3]; + if (src[i*stride] < mn) mn = src[i*stride]; + else if (src[i*stride] > mx) mx = src[i*stride]; } // encode them From be931882efadd4eb49e73786c8cc1f044d94e708 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 11:22:36 -0800 Subject: [PATCH 499/522] update README --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4197a8c..a6f5716 100644 --- a/README.md +++ b/README.md @@ -15,25 +15,25 @@ library | lastest version | category | LoC | description **[stb_image.h](stb_image.h)** | 2.14 | graphics | 7049 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.15 | graphics | 4061 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.05 | graphics | 1092 | image writing to disk: PNG, TGA, BMP -**[stb_image_resize.h](stb_image_resize.h)** | 0.92 | graphics | 2620 | resize images larger/smaller with good quality -**[stb_rect_pack.h](stb_rect_pack.h)** | 0.10 | graphics | 623 | simple 2D rectangle packer with decent quality -**[stb_sprintf.h](stb_sprintf.h)** | 1.02 | utility | 1134 | fast sprintf, snprintf for C/C++ +**[stb_image_resize.h](stb_image_resize.h)** | 0.93 | graphics | 2625 | resize images larger/smaller with good quality +**[stb_rect_pack.h](stb_rect_pack.h)** | 0.11 | graphics | 635 | simple 2D rectangle packer with decent quality +**[stb_sprintf.h](stb_sprintf.h)** | 1.02 | utility | 1202 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 257 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**[stb_textedit.h](stb_textedit.h)** | 1.10 | user interface | 1370 | guts of a text editor for games etc implementing them from scratch -**[stb_voxel_render.h](stb_voxel_render.h)** | 0.84 | 3D graphics | 3792 | Minecraft-esque voxel rendering "engine" with many more features -**[stb_dxt.h](stb_dxt.h)** | 1.05 | 3D graphics | 686 | Fabian "ryg" Giesen's real-time DXT compressor -**[stb_perlin.h](stb_perlin.h)** | 0.2 | 3D graphics | 222 | revised Perlin noise (3D input, 1D output) +**[stb_textedit.h](stb_textedit.h)** | 1.11 | user interface | 1393 | guts of a text editor for games etc implementing them from scratch +**[stb_voxel_render.h](stb_voxel_render.h)** | 0.85 | 3D graphics | 3803 | Minecraft-esque voxel rendering "engine" with many more features +**[stb_dxt.h](stb_dxt.h)** | 1.06 | 3D graphics | 687 | Fabian "ryg" Giesen's real-time DXT compressor +**[stb_perlin.h](stb_perlin.h)** | 0.3 | 3D graphics | 316 | revised Perlin noise (3D input, 1D output) **[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D graphics | 303 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.38 | game dev | 4172 | embeddable tilemap editor **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.6 | game dev | 1220 | herringbone Wang tile map generator **[stb_c_lexer.h](stb_c_lexer.h)** | 0.09 | parsing | 962 | simplify writing parsers for C-like languages **[stb_divide.h](stb_divide.h)** | 0.91 | math | 419 | more useful 32-bit modulus e.g. "euclidean divide" **[stb_connected_comp...](stb_connected_components.h)** | 0.95 | misc | 1045 | incrementally compute reachability on grids -**[stb.h](stb.h)** | 2.28 | misc | 14277 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**[stb.h](stb.h)** | 2.29 | misc | 14324 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.3 | misc | 165 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 50916 +Total lines of C code: 51177 FAQ From 16c83cd5fc4c18954c1b6e3de16c37ba590324a7 Mon Sep 17 00:00:00 2001 From: "Gregory Mullen (grayhatter)" Date: Fri, 3 Mar 2017 11:16:03 -0800 Subject: [PATCH 500/522] Fix a pair of warnings in stb_image.h --- stb_image.h | 75 +++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/stb_image.h b/stb_image.h index 023d247..ce3d47a 100644 --- a/stb_image.h +++ b/stb_image.h @@ -53,7 +53,7 @@ RECENT REVISION HISTORY: 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; - allocate large structures on the stack; + allocate large structures on the stack; correct channel count for PNG & BMP 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED @@ -96,7 +96,7 @@ RECENT REVISION HISTORY: Ryamond Barbiero Paul Du Bois Engin Manap github:snagar Michaelangel007@github Oriol Ferrer Mesia Dale Weiler github:Zelex Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github - Blazej Dariusz Roszkowski github:sammyhw + Blazej Dariusz Roszkowski github:sammyhw GrayHatter@uTox */ @@ -267,11 +267,11 @@ RECENT REVISION HISTORY: // =========================================================================== // // ADDITIONAL CONFIGURATION -// +// // - You can suppress implementation of any of the decoders to reduce // your code footprint by #defining one or more of the following // symbols before creating the implementation. -// +// // STBI_NO_JPEG // STBI_NO_PNG // STBI_NO_BMP @@ -281,11 +281,11 @@ RECENT REVISION HISTORY: // STBI_NO_HDR // STBI_NO_PIC // STBI_NO_PNM (.ppm and .pgm) -// +// // - You can request *only* certain decoders and suppress all other ones // (this will be more forward-compatible, as addition of new decoders // doesn't require you to disable them explicitly): -// +// // STBI_ONLY_JPEG // STBI_ONLY_PNG // STBI_ONLY_BMP @@ -295,7 +295,7 @@ RECENT REVISION HISTORY: // STBI_ONLY_HDR // STBI_ONLY_PIC // STBI_ONLY_PNM (.ppm and .pgm) -// +// // - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still // want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB // @@ -1761,7 +1761,7 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) // magnitude code followed by receive_extend code int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); int m = 1 << (magbits - 1); - if (k < m) k += (-1 << magbits) + 1; + if (k < m) k += (~0U << magbits) + 1; // if the result is small enough, we can fit it in fast_ac table if (k >= -128 && k <= 127) fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); @@ -3594,6 +3594,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { + (void)ri; // This unused warning is safe to ignore. unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); j->s = s; @@ -4605,7 +4606,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); @@ -4888,7 +4889,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); info->mr = info->mg = info->mb = info->ma = 0; - + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { s->img_x = stbi__get16le(s); @@ -4973,7 +4974,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req stbi__bmp_data info; STBI_NOTUSED(ri); - info.all_a = 255; + info.all_a = 255; if (stbi__bmp_parse_header(s, &info) == NULL) return NULL; // error code already set @@ -5092,7 +5093,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req stbi__skip(s, pad); } } - + // if alpha channel is all 0s, replace with all 255s if (target == 4 && all_a == 0) for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) @@ -6537,7 +6538,7 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) void *p; stbi__bmp_data info; - info.all_a = 255; + info.all_a = 255; p = stbi__bmp_parse_header(s, &info); stbi__rewind( s ); if (p == NULL) @@ -7012,38 +7013,38 @@ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ From a4635779882a5350e0a4ae89e307a417cd1a30cd Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 11:47:36 -0800 Subject: [PATCH 501/522] update README w/ MIT info --- README.md | 11 ++++++++--- tools/README.footer.md | 9 +++++++-- tools/README.header.md | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a6f5716..8f51e50 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ stb === -single-file public domain libraries for C/C++ +single-file public domain (or MIT licensed) libraries for C/C++ 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. @@ -45,13 +45,18 @@ These libraries are in the public domain (or the equivalent where that is not possible). 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. + #### 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? +#### If I wrap an stb library in a new library, does the new library have to be public domain/MIT? -No. +No, because it's public domain you can freely relicense it to whatever license your new +library wants to be. #### Some of these libraries seem redundant to existing open source libraries. Are they better somehow? diff --git a/tools/README.footer.md b/tools/README.footer.md index e670b7f..9f263c0 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -8,13 +8,18 @@ These libraries are in the public domain (or the equivalent where that is not possible). 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. + #### 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? +#### If I wrap an stb library in a new library, does the new library have to be public domain/MIT? -No. +No, because it's public domain you can freely relicense it to whatever license your new +library wants to be. #### Some of these libraries seem redundant to existing open source libraries. Are they better somehow? diff --git a/tools/README.header.md b/tools/README.header.md index 847fe62..41e55f1 100644 --- a/tools/README.header.md +++ b/tools/README.header.md @@ -1,7 +1,7 @@ stb === -single-file public domain libraries for C/C++ +single-file public domain (or MIT licensed) libraries for C/C++ 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. From 6f6e11f85fd5c14bc9e9eb5edafb1b5dabd515d0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 11:49:55 -0800 Subject: [PATCH 502/522] readme --- README.md | 6 +++--- tools/README.footer.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8f51e50..5bd0d12 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,8 @@ FAQ #### What's the license? -These libraries are in the public domain (or the equivalent where that is not -possible). You can do anything you want with them. You have no legal obligation +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 @@ -66,7 +66,7 @@ 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? +#### 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. diff --git a/tools/README.footer.md b/tools/README.footer.md index 9f263c0..b492e0a 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -4,8 +4,8 @@ FAQ #### What's the license? -These libraries are in the public domain (or the equivalent where that is not -possible). You can do anything you want with them. You have no legal obligation +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 @@ -29,7 +29,7 @@ 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? +#### 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. From 9e76bb5108cca5c7e853d6a8bbadcd3dfa54b64b Mon Sep 17 00:00:00 2001 From: Jeremy Sawicki Date: Fri, 3 Mar 2017 16:24:21 -0800 Subject: [PATCH 503/522] stb_image: JPEG: Improved detection of RGB images --- stb_image.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/stb_image.h b/stb_image.h index 023d247..416db68 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1691,6 +1691,8 @@ typedef struct int succ_high; int succ_low; int eob_run; + int jfif; + int app14; int rgb; int scan_n, order[4]; @@ -2839,11 +2841,50 @@ static int stbi__process_marker(stbi__jpeg *z, int m) } return L==0; } + // check for comment block or APP blocks if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - stbi__skip(z->s, stbi__get16be(z->s)-2); + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) { + z->jfif = 1; + } + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14 = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); return 1; } + return stbi__err("unknown marker","Corrupt JPEG"); } @@ -3004,6 +3045,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) { int m; + z->jfif = 0; + z->app14 = -1; z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); @@ -3475,7 +3518,7 @@ typedef struct static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { - int n, decode_n; + int n, decode_n, is_rgb; z->s->img_n = 0; // make stbi__cleanup_jpeg safe // validate req_comp @@ -3487,7 +3530,9 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp // determine actual number of components to generate n = req_comp ? req_comp : z->s->img_n; - if (z->s->img_n == 3 && n < 3 && z->rgb != 3) + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14 == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) decode_n = 1; else decode_n = z->s->img_n; @@ -3547,7 +3592,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (n >= 3) { stbi_uc *y = coutput[0]; if (z->s->img_n == 3) { - if (z->rgb == 3) { + if (is_rgb) { for (i=0; i < z->s->img_x; ++i) { out[0] = y[i]; out[1] = coutput[1][i]; @@ -3565,7 +3610,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp out += n; } } else { - if (z->rgb == 3) { + if (is_rgb) { if (n == 1) for (i=0; i < z->s->img_x; ++i) *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); From 3e1754487307572b81a51350efe99f4d31fb52e3 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sat, 4 Mar 2017 20:49:14 -0800 Subject: [PATCH 504/522] stb_image: Give up trying to runtime-detect SSE2 on GCC. We tried but it was nothing but trouble. New rule: with GCC/Clang, if you're compiling with -msse2, you get always-on SSE2 code, otherwise you don't get any. Trying to ship anything with proper runtime dispatch requires both working around certain bugs and some fiddling with build settings, which runs contrary to the intent of a one-file library, so bail on it entirely. Fixes issue #280. Fixes issue #410. --- stb_image.h | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/stb_image.h b/stb_image.h index 023d247..bcfb5fa 100644 --- a/stb_image.h +++ b/stb_image.h @@ -583,12 +583,14 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI__X86_TARGET #endif -#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) -// NOTE: not clear do we actually need this for the 64-bit path? +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, -// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; -// this is just broken and gcc are jerks for not fixing it properly -// http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. #define STBI_NO_SIMD #endif @@ -646,14 +648,10 @@ static int stbi__sse2_available() static int stbi__sse2_available() { -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later - // GCC 4.8+ has a nice way to do this - return __builtin_cpu_supports("sse2"); -#else - // portable way to do this, preferably without using GCC inline ASM? - // just bail for now. - return 0; -#endif + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; } #endif #endif From 22c72a069c8e8ef666374e07db3657ba721a7943 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sat, 4 Mar 2017 21:17:09 -0800 Subject: [PATCH 505/522] stb_image: Support optional args consistently. My guideline for the rules is the PNG loader (which I consider "canonical"). In the _load functions, x and y are required but comp is optional; in the _info functions, all three are optional. Fixes issue #411 (and other related, unreported issues). --- stb_image.h | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/stb_image.h b/stb_image.h index 023d247..c424f6c 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5875,9 +5875,11 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) { stbi_uc *result; - int i, x,y; + int i, x,y, internal_comp; STBI_NOTUSED(ri); + if (!comp) comp = &internal_comp; + for (i=0; i<92; ++i) stbi__get8(s); @@ -6496,6 +6498,11 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) char buffer[STBI__HDR_BUFLEN]; char *token; int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; if (stbi__hdr_test(s) == 0) { stbi__rewind( s ); @@ -6542,9 +6549,9 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) stbi__rewind( s ); if (p == NULL) return 0; - *x = s->img_x; - *y = s->img_y; - *comp = info.ma ? 4 : 3; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) *comp = info.ma ? 4 : 3; return 1; } #endif @@ -6552,7 +6559,10 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) #ifndef STBI_NO_PSD static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) { - int channelCount; + int channelCount, dummy; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; @@ -6585,9 +6595,13 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) #ifndef STBI_NO_PIC static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) { - int act_comp=0,num_packets=0,chained; + int act_comp=0,num_packets=0,chained,dummy; stbi__pic_packet packets[10]; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { stbi__rewind(s); return 0; @@ -6673,7 +6687,7 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req *x = s->img_x; *y = s->img_y; - *comp = s->img_n; + if (comp) *comp = s->img_n; if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) return stbi__errpuc("too large", "PNM too large"); @@ -6727,16 +6741,20 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c) static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) { - int maxv; + int maxv, dummy; char c, p, t; - stbi__rewind( s ); + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); // Get identifier p = (char) stbi__get8(s); t = (char) stbi__get8(s); if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind( s ); + stbi__rewind(s); return 0; } From 667f35578b4cb6950ec381235fd41c0c5bd56aba Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 8 Mar 2017 21:16:50 +0500 Subject: [PATCH 506/522] statically initialize --- stb_image.h | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/stb_image.h b/stb_image.h index 023d247..9fcc326 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3680,7 +3680,7 @@ stbi_inline static int stbi__bit_reverse(int v, int bits) return stbi__bitreverse16(v) >> (16-bits); } -static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) { int i,k=0; int code, next_code[16], sizes[17]; @@ -3970,9 +3970,33 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) return 1; } -// @TODO: should statically initialize these for optimal thread safety -static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; -static void stbi__init_zdefaults(void) +static const stbi_uc stbi__zdefault_length[288] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8 +}; +static const stbi_uc stbi__zdefault_distance[32] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; +/* +Init algorithm: { int i; // use <= to match clearly with spec for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; @@ -3982,6 +4006,7 @@ static void stbi__init_zdefaults(void) for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; } +*/ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) { @@ -4000,7 +4025,6 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) } else { if (type == 1) { // use fixed code lengths - if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; } else { From a99bc0ca326299e65ed5a929996efaf1431e8dd1 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Sat, 11 Mar 2017 09:34:26 -0800 Subject: [PATCH 507/522] Fix a bunch of warnings under Apple's clang-800.0.42.1 --- stb_image_resize.h | 88 +++++++++++++++++++---------------------- tests/resample_test.cpp | 12 +++--- tests/resample_test_c.c | 3 ++ 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 87bbd11..e563165 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -551,16 +551,17 @@ typedef struct int encode_buffer_size; } stbir__info; + +static const double stbir__max_uint8_as_float = 255.0f; +static const double stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0f; + + static stbir__inline int stbir__min(int a, int b) { return a < b ? a : b; } -static stbir__inline int stbir__max(int a, int b) -{ - return a > b ? a : b; -} - static stbir__inline float stbir__saturate(float x) { if (x < 0) @@ -1027,7 +1028,7 @@ static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radi *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); } -static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) { int i; float total_filter = 0; @@ -1077,7 +1078,7 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi } } -static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) { int i; @@ -1107,7 +1108,7 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st } } -static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) { int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); @@ -1184,7 +1185,7 @@ static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, st // Each scan line uses the same kernel values so we should calculate the kernel // values once and then we can use them for every scan line. -static void stbir__calculate_filters(stbir__info* stbir_info, stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) { int n; int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); @@ -1201,7 +1202,7 @@ static void stbir__calculate_filters(stbir__info* stbir_info, stbir__contributor stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); - stbir__calculate_coefficients_upsample(stbir_info, filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); } } else @@ -1217,10 +1218,10 @@ static void stbir__calculate_filters(stbir__info* stbir_info, stbir__contributor stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); - stbir__calculate_coefficients_downsample(stbir_info, filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); } - stbir__normalize_downsample_coefficients(stbir_info, contributors, coefficients, filter, scale_ratio, shift, input_size, output_size); + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); } } @@ -1270,7 +1271,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / 255; + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; } break; @@ -1283,7 +1284,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / 255; + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; } break; @@ -1293,7 +1294,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / 65535; + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; } break; @@ -1303,10 +1304,10 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / 65535); + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / 65535; + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; } break; @@ -1316,7 +1317,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / 4294967295); + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); } break; @@ -1326,10 +1327,10 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / 4294967295)); + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / 4294967295); + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); } break; @@ -1431,11 +1432,10 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) } -static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, float* output_buffer) +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) { int x, k; int output_w = stbir_info->output_w; - int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width; int channels = stbir_info->channels; float* decode_buffer = stbir__get_decode_buffer(stbir_info); stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; @@ -1515,12 +1515,10 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, } } -static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n, float* output_buffer) +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) { int x, k; int input_w = stbir_info->input_w; - int output_w = stbir_info->output_w; - int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width; int channels = stbir_info->channels; float* decode_buffer = stbir__get_decode_buffer(stbir_info); stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; @@ -1654,9 +1652,9 @@ static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) // Now resample it into the ring buffer. if (stbir__use_width_upsampling(stbir_info)) - stbir__resample_horizontal_upsample(stbir_info, n, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); else - stbir__resample_horizontal_downsample(stbir_info, n, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. } @@ -1670,9 +1668,9 @@ static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n // Now resample it into the horizontal buffer. if (stbir__use_width_upsampling(stbir_info)) - stbir__resample_horizontal_upsample(stbir_info, n, stbir_info->horizontal_buffer); + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); else - stbir__resample_horizontal_downsample(stbir_info, n, stbir_info->horizontal_buffer); + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. } @@ -1723,11 +1721,11 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) #ifdef STBIR__SATURATE_INT - #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * 255 )) - #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * 65535)) + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) #else - #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * 255 ) - #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * 65535) + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) #endif switch (decode) @@ -1782,7 +1780,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void for (n = 0; n < num_nonalpha; n++) { int index = pixel_index + nonalpha[n]; - ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * 65535); + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); } if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) @@ -1799,7 +1797,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void for (n = 0; n < channels; n++) { int index = pixel_index + n; - ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * 4294967295); + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); } } break; @@ -1812,11 +1810,11 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void for (n = 0; n < num_nonalpha; n++) { int index = pixel_index + nonalpha[n]; - ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * 4294967295); + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); } if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * 4294967295); + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); } break; @@ -1855,7 +1853,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void } } -static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, int in_first_scanline, int in_last_scanline, float in_center_of_out) +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) { int x, k; int output_w = stbir_info->output_w; @@ -1876,7 +1874,6 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in float* ring_buffer = stbir_info->ring_buffer; int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; - int ring_buffer_last_scanline = stbir_info->ring_buffer_last_scanline; int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); int n0,n1, output_row_start; @@ -1973,16 +1970,14 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); } -static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, int in_first_scanline, int in_last_scanline, float in_center_of_out) +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) { int x, k; int output_w = stbir_info->output_w; - int output_h = stbir_info->output_h; stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; float* vertical_coefficients = stbir_info->vertical_coefficients; int channels = stbir_info->channels; int ring_buffer_entries = stbir_info->ring_buffer_num_entries; - void* output_data = stbir_info->output_data; float* horizontal_buffer = stbir_info->horizontal_buffer; int coefficient_width = stbir_info->vertical_coefficient_width; int contributor = n + stbir_info->vertical_filter_pixel_margin; @@ -1990,7 +1985,6 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, float* ring_buffer = stbir_info->ring_buffer; int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; - int ring_buffer_last_scanline = stbir_info->ring_buffer_last_scanline; int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); int n0,n1; @@ -2103,7 +2097,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); // Now all buffers should be ready to write a row of vertical sampling. - stbir__resample_vertical_upsample(stbir_info, y, in_first_scanline, in_last_scanline, in_center_of_out); + stbir__resample_vertical_upsample(stbir_info, y); STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); } @@ -2189,7 +2183,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); // Now the horizontal buffer is ready to write to all ring buffer rows. - stbir__resample_vertical_downsample(stbir_info, y, out_first_scanline, out_last_scanline, out_center_of_in); + stbir__resample_vertical_downsample(stbir_info, y); } stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); @@ -2393,8 +2387,8 @@ static int stbir__resize_allocated(stbir__info *info, // This signals that the ring buffer is empty info->ring_buffer_begin_index = -1; - stbir__calculate_filters(info, info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); - stbir__calculate_filters(info, info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); STBIR_PROGRESS_REPORT(0); diff --git a/tests/resample_test.cpp b/tests/resample_test.cpp index 2c4a56a..882dcc0 100644 --- a/tests/resample_test.cpp +++ b/tests/resample_test.cpp @@ -70,9 +70,11 @@ void stbir_progress(float p) #ifdef _WIN32 #include -#endif - #include +#define mkdir(a, b) _mkdir(a) +#else +#include +#endif #define MT_SIZE 624 static size_t g_aiMT[MT_SIZE]; @@ -833,7 +835,7 @@ void test_filters(void) #define UMAX32 4294967295U -static void write32(char *filename, stbir_uint32 *output, int w, int h) +static void write32(const char *filename, stbir_uint32 *output, int w, int h) { stbir_uint8 *data = (stbir_uint8*) malloc(w*h*3); for (int i=0; i < w*h*3; ++i) @@ -869,9 +871,9 @@ static void test_32(void) void test_suite(int argc, char **argv) { int i; - char *barbara; + const char *barbara; - _mkdir("test-output"); + mkdir("test-output", 777); if (argc > 1) barbara = argv[1]; diff --git a/tests/resample_test_c.c b/tests/resample_test_c.c index 50520c6..e7e3531 100644 --- a/tests/resample_test_c.c +++ b/tests/resample_test_c.c @@ -3,3 +3,6 @@ #include "stb_image_resize.h" // Just to make sure it will build properly with a c compiler + +int main() { +} From 1adb98f1425115d821d26aee8f92a4efa1ac7734 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Tue, 14 Mar 2017 19:13:00 -0700 Subject: [PATCH 508/522] Fix some MSVC /W4 warnings --- stb_image_resize.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index e563165..5499ded 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -552,9 +552,9 @@ typedef struct } stbir__info; -static const double stbir__max_uint8_as_float = 255.0f; -static const double stbir__max_uint16_as_float = 65535.0f; -static const double stbir__max_uint32_as_float = 4294967295.0f; +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; static stbir__inline int stbir__min(int a, int b) @@ -1713,9 +1713,13 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void // build a table of all channels that need colorspace correction, so // we don't perform colorspace correction on channels that don't need it. - for (x=0, num_nonalpha=0; x < channels; ++x) - if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) - nonalpha[num_nonalpha++] = x; + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) From 72e0f6c971b668b8b7a3ac31b33614f7edecd35b Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Tue, 14 Mar 2017 19:35:51 -0700 Subject: [PATCH 509/522] Fix whitespace to how Sean likes it --- stb_image_resize.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index 5499ded..c13871c 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1713,13 +1713,13 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void // build a table of all channels that need colorspace correction, so // we don't perform colorspace correction on channels that don't need it. - for (x = 0, num_nonalpha = 0; x < channels; ++x) - { - if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) - { + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { nonalpha[num_nonalpha++] = (stbir_uint16)x; - } - } + } + } #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) From be6d13cd6df7d1e2e842ccc4b271b9d8d7c852ef Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 10:54:22 -0700 Subject: [PATCH 510/522] fix bug in png decoding with 1,2,4-bpp images using filter that samples previous line --- stb_image.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 023d247..119c55f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4201,7 +4201,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r for (j=0; j < y; ++j) { stbi_uc *cur = a->out + stride*j; - stbi_uc *prior = cur - stride; + stbi_uc *prior; int filter = *raw++; if (filter > 4) @@ -4213,6 +4213,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r filter_bytes = 1; width = img_width_bytes; } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; From 5bbe1d8c2a22ad7833dd40c82ed2d3df0aa44e1b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:03:34 -0700 Subject: [PATCH 511/522] fixes to that PR --- stb_image.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index c220032..f4682c7 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.14 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.15 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -48,6 +48,7 @@ LICENSE RECENT REVISION HISTORY: + 2.15 (2017-03-18) fix png-1,2,4 bug; warnings 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes @@ -77,7 +78,7 @@ RECENT REVISION HISTORY: Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) github:urraka (animated gif) Junggon Kim (PNM comments) Daniel Gibson (16-bit TGA) - socks-the-fox (16-bit TGA) + socks-the-fox (16-bit PNG) Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Fabian "ryg" Giesen @@ -96,7 +97,7 @@ RECENT REVISION HISTORY: Ryamond Barbiero Paul Du Bois Engin Manap github:snagar Michaelangel007@github Oriol Ferrer Mesia Dale Weiler github:Zelex Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github - Blazej Dariusz Roszkowski github:sammyhw GrayHatter@uTox + Blazej Dariusz Roszkowski github:sammyhw Gregory Mullen */ @@ -3594,9 +3595,9 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { - (void)ri; // This unused warning is safe to ignore. unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); result = load_jpeg_image(j, x,y,comp,req_comp); From 8fe48099cced44033981ac4114abbd983638645c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:07:51 -0700 Subject: [PATCH 512/522] add comment for next fix prematurely --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index f4682c7..1d7843c 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.15 (2017-03-18) fix png-1,2,4 bug; warnings + 2.15 (2017-03-18) fix png-1,2,4 bug; warnings; all Imagenet JPGs decode 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes From 6d606103482631d4cf6cebd1a2d48602aa8c7b6b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:15:41 -0700 Subject: [PATCH 513/522] tweaks to previous merge --- stb_image.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stb_image.h b/stb_image.h index bd83c14..2a40cd7 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1693,7 +1693,7 @@ typedef struct int succ_low; int eob_run; int jfif; - int app14; + int app14_color_transform; // Adobe APP14 tag int rgb; int scan_n, order[4]; @@ -2862,9 +2862,8 @@ static int stbi__process_marker(stbi__jpeg *z, int m) if (stbi__get8(z->s) != tag[i]) ok = 0; L -= 5; - if (ok) { + if (ok) z->jfif = 1; - } } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; int ok = 1; @@ -2877,7 +2876,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m) stbi__get8(z->s); // version stbi__get16be(z->s); // flags0 stbi__get16be(z->s); // flags1 - z->app14 = stbi__get8(z->s); // color transform + z->app14_color_transform = stbi__get8(z->s); // color transform L -= 6; } } @@ -3047,7 +3046,7 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) { int m; z->jfif = 0; - z->app14 = -1; + z->app14_color_transform = -1; // valid values are 0,1,2 z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); @@ -3531,7 +3530,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp // determine actual number of components to generate n = req_comp ? req_comp : z->s->img_n; - is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14 == 0 && !z->jfif)); + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); if (z->s->img_n == 3 && n < 3 && !is_rgb) decode_n = 1; From 24fa8161166327af9f9d35cabf520d69d233a04e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:31:06 -0700 Subject: [PATCH 514/522] merge https://github.com/nothings/stb/pull/427 but I messed up the merge so you don't get the automatic info you normally do --- stb_image.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/stb_image.h b/stb_image.h index 2a40cd7..2a1d264 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2628,7 +2628,7 @@ static void stbi__jpeg_reset(stbi__jpeg *j) j->code_bits = 0; j->code_buffer = 0; j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; j->marker = STBI__MARKER_none; j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; j->eob_run = 0; @@ -2959,7 +2959,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires c = stbi__get8(s); - if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); s->img_n = c; for (i=0; i < c; ++i) { z->img_comp[i].data = NULL; @@ -2972,7 +2972,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) for (i=0; i < s->img_n; ++i) { static unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); - if (z->img_comp[i].id == rgb[i]) + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) ++z->rgb; q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); @@ -3516,6 +3516,13 @@ typedef struct int ypos; // which pre-expansion row we're on } stbi__resample; +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { int n, decode_n, is_rgb; @@ -3528,7 +3535,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } // determine actual number of components to generate - n = req_comp ? req_comp : z->s->img_n; + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); @@ -3603,6 +3610,28 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } else { z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], k); + out[1] = stbi__blinn_8x8(coutput[1][i], k); + out[2] = stbi__blinn_8x8(coutput[2][i], k); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], k); + out[1] = stbi__blinn_8x8(255 - out[1], k); + out[2] = stbi__blinn_8x8(255 - out[2], k); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } } else for (i=0; i < z->s->img_x; ++i) { out[0] = out[1] = out[2] = y[i]; @@ -3620,6 +3649,22 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp out[1] = 255; } } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], k); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], k); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], k); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } } else { stbi_uc *y = coutput[0]; if (n == 1) @@ -3632,7 +3677,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp stbi__cleanup_jpeg(z); *out_x = z->s->img_x; *out_y = z->s->img_y; - if (comp) *comp = z->s->img_n; // report original components, not output + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output return output; } } @@ -3669,7 +3714,7 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) } if (x) *x = j->s->img_x; if (y) *y = j->s->img_y; - if (comp) *comp = j->s->img_n; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; return 1; } From d9e7c55bd7ddefa31e6b8e44b053083b260d3b65 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:35:30 -0700 Subject: [PATCH 515/522] minor docs for last merge --- stb_image.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index d38bfcd..f2c8216 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.15 (2017-03-18) fix png-1,2,4 bug; warnings; all Imagenet JPGs decode + 2.15 (2017-03-18) fix png-1,2,4 bug; all Imagenet JPGs decode 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes @@ -6933,6 +6933,9 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) allocate large structures on the stack From 2de9961443d443c7c3e13a7c0c6577881d4295f7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:39:06 -0700 Subject: [PATCH 516/522] docs --- stb_image.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 87b8a07..563a857 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6952,7 +6952,8 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; - warning fixes; disable run-time SSE detection on gcc + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes From c79fa78ee8e4ee82bf887218ec82c9aa10a98308 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:42:54 -0700 Subject: [PATCH 517/522] tweaks to previous merge --- stb_image.h | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/stb_image.h b/stb_image.h index c9a50f1..1de3a4f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4059,30 +4059,21 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) return 1; } -static const stbi_uc stbi__zdefault_length[288] = { - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8 +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 }; -static const stbi_uc stbi__zdefault_distance[32] = { - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 }; /* Init algorithm: @@ -6977,7 +6968,8 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int revision history: 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; warning fixes; disable run-time SSE detection on gcc; - uniform handling of optional "return" values + uniform handling of optional "return" values; + thread-safe initialization of zlib tables 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes From 56a61e178f8b4e30fd1a148dd94ef81b7b921287 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:48:09 -0700 Subject: [PATCH 518/522] reorganize contributor list (removing one redundant name and adding one new one as well) --- stb_image.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/stb_image.h b/stb_image.h index 1de3a4f..de0a0b5 100644 --- a/stb_image.h +++ b/stb_image.h @@ -86,18 +86,18 @@ RECENT REVISION HISTORY: Bug & warning fixes Marc LeBlanc David Woo Guillaume George Martins Mozeiko - Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson - Dave Moore Roy Eltham Hayaki Saito Phil Jordan - Won Chun Luke Graham Johan Duparc Nathan Reed - the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis - Janez Zemva John Bartholomew Michal Cichon github:svdijk - Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson - Laurent Gomila Cort Stratton Sergio Gonzalez github:romigrou - Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan - Ryamond Barbiero Paul Du Bois Engin Manap github:snagar - Michaelangel007@github Oriol Ferrer Mesia Dale Weiler github:Zelex - Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github - Blazej Dariusz Roszkowski github:sammyhw Gregory Mullen + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier Baldur Karlsson + Janez Zemva John Bartholomew Michal Cichon github:rlyeh + Jonathan Blow Ken Hamada Tero Hanninen github:romigrou + Laurent Gomila Cort Stratton Sergio Gonzalez github:svdijk + Aruelien Pocheville Thibault Reuille Cass Everitt github:snagar + Ryamond Barbiero Paul Du Bois Engin Manap github:Zelex + Michaelangel007@github Philipp Wiesemann Dale Weiler github:grim210 + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:sammyhw + Blazej Dariusz Roszkowski Gregory Mullen github:phprus */ From d795785f3dc9f0ae09909554bc1f645368f7d448 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:50:06 -0700 Subject: [PATCH 519/522] docs --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index de0a0b5..ae2ada6 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.15 (2017-03-18) fix png-1,2,4 bug; all Imagenet JPGs decode + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes From c0539b4ea5c168bc91dceea2c0d1431b60794c04 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:55:13 -0700 Subject: [PATCH 520/522] version; tweak docs --- stb_image_resize.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index c13871c..b507e04 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -1,4 +1,4 @@ -/* stb_image_resize - v0.93 - public domain image resizing +/* stb_image_resize - v0.94 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb @@ -107,8 +107,8 @@ industry, it is still uncommon in the videogame/real-time world. If you linearly filter non-premultiplied alpha, strange effects - occur. (For example, the average of 1% opaque bright green - and 99% opaque black produces 50% transparent dark green when + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when non-premultiplied, whereas premultiplied it produces 50% transparent near-black. The former introduces green energy that doesn't exist in the source image.) @@ -152,18 +152,19 @@ (For example, graphics hardware does not apply sRGB conversion to the alpha channel.) - ADDITIONAL CONTRIBUTORS + CONTRIBUTORS + Jorge L Rodriguez: Implementation Sean Barrett: API design, optimizations Aras Pranckevicius: bugfix REVISIONS + 0.94 (2017-03-18) fixed warnings 0.93 (2017-03-03) fixed bug with certain combinations of heights 0.92 (2017-01-02) fix integer overflow on large (>2GB) images 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions 0.90 (2014-09-17) first released version LICENSE - See end of file for license information. TODO From f1417efd36ef00b457b83d032936eb48c4658b37 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 18 Mar 2017 18:55:29 -0700 Subject: [PATCH 521/522] update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5bd0d12..4d9d323 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,10 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.10 | audio | 5447 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.14 | graphics | 7049 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_image.h](stb_image.h)** | 2.15 | graphics | 7177 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.15 | graphics | 4061 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.05 | graphics | 1092 | image writing to disk: PNG, TGA, BMP -**[stb_image_resize.h](stb_image_resize.h)** | 0.93 | graphics | 2625 | resize images larger/smaller with good quality +**[stb_image_resize.h](stb_image_resize.h)** | 0.94 | graphics | 2624 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.11 | graphics | 635 | simple 2D rectangle packer with decent quality **[stb_sprintf.h](stb_sprintf.h)** | 1.02 | utility | 1202 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.02 | utility | 257 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.3 | misc | 165 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 51177 +Total lines of C code: 51304 FAQ From c7110588a4d24c4bb5155c184fbb77dd90b3116e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 19 Mar 2017 17:51:43 -0700 Subject: [PATCH 522/522] update README with info about SSE2 on GCC --- README.md | 16 ++++++++++++++++ tools/README.footer.md | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/README.md b/README.md index 4d9d323..7d6d82c 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,22 @@ dual-license for you to choose from. 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, diff --git a/tools/README.footer.md b/tools/README.footer.md index b492e0a..f6f4bf5 100644 --- a/tools/README.footer.md +++ b/tools/README.footer.md @@ -21,6 +21,22 @@ dual-license for you to choose from. 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,