From 13942348e08e1b68fa439a5fabf8baf108466bb0 Mon Sep 17 00:00:00 2001 From: Tim Wright Date: Tue, 18 Apr 2017 19:54:57 -0600 Subject: [PATCH 01/99] Fixing void * compile error for C++ --- stretchy_buffer.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stretchy_buffer.h b/stretchy_buffer.h index bb711f6..bc11083 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -162,6 +162,10 @@ // 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. // +// Contributors: +// +// Timothy Wright (github:ZenToad) +// // LICENSE // // See end of file for license information. @@ -189,7 +193,7 @@ #define stb__sbneedgrow(a,n) ((a)==0 || stb__sbn(a)+(n) >= stb__sbm(a)) #define stb__sbmaybegrow(a,n) (stb__sbneedgrow(a,(n)) ? stb__sbgrow(a,n) : 0) -#define stb__sbgrow(a,n) ((a) = stb__sbgrowf((a), (n), sizeof(*(a)))) +#define stb__sbgrow(a,n) (*((void **)&(a)) = stb__sbgrowf((a), (n), sizeof(*(a)))) #include From 84e42c2e8d2a94f936ebcf7ce14a8e02d2e8be6e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 28 Apr 2017 23:35:37 -0700 Subject: [PATCH 02/99] fix stbi_shiftsigned to be shifting a value that's unsigned --- stb_image.h | 5 +++-- tests/caveview/cave_mesher.c | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index ae2ada6..a81c5ac 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4960,7 +4960,7 @@ static int stbi__bitcount(unsigned int a) return a & 0xff; } -static int stbi__shiftsigned(int v, int shift, int bits) +static unsigned int stbi__shiftsigned(unsigned int v, int shift, int bits) { int result; int z=0; @@ -4969,6 +4969,7 @@ static int stbi__shiftsigned(int v, int shift, int bits) else v >>= shift; result = v; + // replicate the high bits to the low bits z = bits; while (z < 8) { result += v >> z; @@ -5185,7 +5186,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req 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; + unsigned int a; out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); diff --git a/tests/caveview/cave_mesher.c b/tests/caveview/cave_mesher.c index 1fac297..1f76c89 100644 --- a/tests/caveview/cave_mesher.c +++ b/tests/caveview/cave_mesher.c @@ -37,7 +37,8 @@ extern void ods(char *fmt, ...); #define FAST_CHUNK #define IN_PLACE -#define SKIP_TERRAIN 48 // use to avoid building underground stuff +#define SKIP_TERRAIN 0 +//#define SKIP_TERRAIN 48 // use to avoid building underground stuff // allows you to see what perf would be like if underground was efficiently culled, // or if you were making a game without underground @@ -131,7 +132,8 @@ unsigned char minecraft_info[256][7] = { C_solid, 35,35,35,35,4,4, }, // 48 - { C_solid, 36,36,36,36,36,36 }, + //{ C_solid, 36,36,36,36,36,36 }, + { C_force, 36,36,36,36,36,36 }, { C_solid, 37,37,37,37,37,37 }, { C_cross, 80,80,80,80,80,80 }, // torch { C_empty }, // fire @@ -142,6 +144,7 @@ unsigned char minecraft_info[256][7] = // 56 { C_solid, 50,50,50,50,50,50 }, + //{ C_force, 50,50,50,50,50,50 }, { C_solid, 26,26,26,26,26,26 }, { C_solid, 60,59,59,59,43,43 }, { C_cross, 95,95,95,95 }, @@ -831,6 +834,8 @@ void mesh_init(void) minecraft_color_for_blocktype[161][i] = 37 | 64; // green minecraft_color_for_blocktype[10][i] = 63; // emissive lava minecraft_color_for_blocktype[11][i] = 63; // emissive + //minecraft_color_for_blocktype[56][i] = 63; // emissive diamond + minecraft_color_for_blocktype[48][i] = 63; // emissive dungeon } #ifdef VHEIGHT_TEST From e6bbecd3a9c73be061aeb51d6e4fe19317bc4d89 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 4 Jul 2017 18:07:33 +0200 Subject: [PATCH 03/99] stb_image_write.h: Set PNG compress lvl via stbi_write_png_level This allows the user to change the deflate/zlib compress level used for PNG compression by changing a global variable. --- stb_image_write.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index df62339..44c8943 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -73,6 +73,9 @@ USAGE: writer, both because it is in BGR order and because it may have padding at the end of the line.) + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_level' (it defaults to 8). + HDR expects linear float data. Since the format is always 32-bit rgb(e) data, alpha (if provided) is discarded, and for monochrome data it is replicated across all three channels. @@ -124,6 +127,7 @@ extern "C" { #else #define STBIWDEF extern extern int stbi_write_tga_with_rle; +extern int stbi_write_png_level; #endif #ifndef STBI_WRITE_NO_STDIO @@ -894,6 +898,12 @@ static unsigned char stbiw__paeth(int a, int b, int c) return STBIW_UCHAR(c); } +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_png_level = 8; +#else +int stbi_write_png_level = 8; +#endif + // @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) { @@ -949,7 +959,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); } STBIW_FREE(line_buffer); - zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_level); STBIW_FREE(filt); if (!zlib) return 0; From be21113512b4c1ab8a9fce23d5ad9ca4184bc25e Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 4 Jul 2017 19:34:31 +0200 Subject: [PATCH 04/99] stb_image_write.h: Allow setting custom zlib compress function for PNG The builtin stbi_zlib_compress does not compress as well as zlib or miniz (which is not too surprising as it's <200 LOC), thus PNGs created by stb_image_write are about 20-50% bigger than PNGs compressed with libpng. This change lets the user supply a custom deflate/zlib-style compress function, which improves compression a lot. This was requested in #113. Example for zlib: #include unsigned char* compress_for_stbiw(unsigned char *data, int data_len, int *out_len, int quality) { uLongf bufSize = compressBound(data_len); // note that buf will be free'd by stb_image_write.h // with STBIW_FREE() (plain free() by default) unsigned char* buf = malloc(bufSize); if(buf == NULL) return NULL; if(compress2(buf, &bufSize, data, data_len, quality) != Z_OK) { free(buf); return NULL; } *out_len = bufSize; return buf; } #define STBIW_ZLIB_COMPRESS compress_for_stbiw #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" // ... --- stb_image_write.h | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 44c8943..a084364 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -16,16 +16,22 @@ ABOUT: adapted to write to memory or a general streaming interface; let me know. 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 simplicity, not optimal image file size - or run-time performance. + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. BUILDING: You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace malloc,realloc,free. - You can define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), USAGE: @@ -650,6 +656,7 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da // PNG writer // +#ifndef STBIW_ZLIB_COMPRESS // 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] @@ -730,8 +737,14 @@ static unsigned int stbiw__zhash(unsigned char *data) #define stbiw__ZHASH 16384 +#endif // STBIW_ZLIB_COMPRESS + unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) { +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; @@ -833,6 +846,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l // make returned pointer freeable STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS } static unsigned int stbiw__crc32(unsigned char *buffer, int len) From d74530cd10680debdd5a9765644f5e366a01aebb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 5 Jul 2017 18:01:53 -0700 Subject: [PATCH 05/99] fix stb_fclose to do a better job of preserving content --- stb.h | 128 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 38 deletions(-) diff --git a/stb.h b/stb.h index edd2e1b..aab6820 100644 --- a/stb.h +++ b/stb.h @@ -1024,8 +1024,8 @@ stb__wchar *stb__from_utf8(char *str) stb__wchar *stb__from_utf8_alt(char *str) { - static stb__wchar buffer[64]; - return stb_from_utf8(buffer, str, 64); + static stb__wchar buffer[4096]; + return stb_from_utf8(buffer, str, 4096); } char *stb__to_utf8(stb__wchar *str) @@ -5435,63 +5435,73 @@ typedef struct int errors; } stb__file_data; -FILE * stb_fopen(char *filename, char *mode) +static FILE *stb__open_temp_file(char *temp_name, char *src_name, char *mode) { - FILE *f; - char name_full[4096]; - char temp_full[sizeof(name_full) + 12]; int p; #ifdef _MSC_VER int j; #endif - if (mode[0] != 'w' && !strchr(mode, '+')) - return stb__fopen(filename, mode); - - // save away the full path to the file so if the program - // changes the cwd everything still works right! unix has - // better ways to do this, but we have to work in windows - name_full[0] = '\0'; // stb_fullpath reads name_full[0] - if (stb_fullpath(name_full, sizeof(name_full), filename)==0) - return 0; - + FILE *f; // try to generate a temporary file in the same directory - p = strlen(name_full)-1; - while (p > 0 && name_full[p] != '/' && name_full[p] != '\\' - && name_full[p] != ':' && name_full[p] != '~') + p = strlen(src_name)-1; + while (p > 0 && src_name[p] != '/' && src_name[p] != '\\' + && src_name[p] != ':' && src_name[p] != '~') --p; ++p; - memcpy(temp_full, name_full, p); + memcpy(temp_name, src_name, p); #ifdef _MSC_VER // try multiple times to make a temp file... just in // case some other process makes the name first for (j=0; j < 32; ++j) { - strcpy(temp_full+p, "stmpXXXXXX"); - if (stb_mktemp(temp_full) == NULL) + strcpy(temp_name+p, "stmpXXXXXX"); + if (stb_mktemp(temp_name) == NULL) return 0; - f = fopen(temp_full, mode); + f = fopen(temp_name, mode); if (f != NULL) break; } #else { - strcpy(temp_full+p, "stmpXXXXXX"); + strcpy(temp_name+p, "stmpXXXXXX"); #ifdef __MINGW32__ - int fd = open(mktemp(temp_full), O_RDWR); + int fd = open(mktemp(temp_name), O_RDWR); #else - int fd = mkstemp(temp_full); + int fd = mkstemp(temp_name); #endif if (fd == -1) return NULL; f = fdopen(fd, mode); if (f == NULL) { - unlink(temp_full); + unlink(temp_name); close(fd); return NULL; } } #endif + return f; +} + + +FILE * stb_fopen(char *filename, char *mode) +{ + FILE *f; + char name_full[4096]; + char temp_full[sizeof(name_full) + 12]; + + // @TODO: if the file doesn't exist, we can also use the fastpath here + if (mode[0] != 'w' && !strchr(mode, '+')) + return stb__fopen(filename, mode); + + // save away the full path to the file so if the program + // changes the cwd everything still works right! unix has + // better ways to do this, but we have to work in windows + name_full[0] = '\0'; // stb_fullpath reads name_full[0] + if (stb_fullpath(name_full, sizeof(name_full), filename)==0) + return 0; + + f = stb__open_temp_file(temp_full, name_full, mode); if (f != NULL) { stb__file_data *d = (stb__file_data *) malloc(sizeof(*d)); if (!d) { assert(0); /* NOTREACHED */fclose(f); return NULL; } @@ -5534,21 +5544,63 @@ int stb_fclose(FILE *f, int keep) } } - if (keep != stb_keep_no) { - if (stb_fexists(d->name) && remove(d->name)) { - // failed to delete old, so don't keep new - keep = stb_keep_no; + if (keep == stb_keep_no) { + remove(d->temp_name); + } else { + if (!stb_fexists(d->name)) { + // old file doesn't exist, so just move the new file over it + stb_rename(d->temp_name, d->name); } else { - if (!stb_rename(d->temp_name, d->name)) - ok = STB_TRUE; - else - keep=stb_keep_no; + // don't delete the old file yet in case there are troubles! First rename it! + char preserved_old_file[4096]; + + // generate a temp filename in the same directory (also creates it, which we don't need) + FILE *dummy = stb__open_temp_file(preserved_old_file, d->name, "wb"); + if (dummy != NULL) { + // we don't actually want the open file + fclose(dummy); + + // discard what we just created + remove(preserved_old_file); // if this fails, there's nothing we can do, and following logic handles it as best as possible anyway + + // move the existing file to the preserved name + if (0 != stb_rename(d->name, preserved_old_file)) { // 0 on success + // failed, state is: + // filename -> old file + // tempname -> new file + // keep tempname around so we don't lose data + } else { + // state is: + // preserved -> old file + // tempname -> new file + // move the new file to the old name + if (0 == stb_rename(d->temp_name, d->name)) { + // state is: + // preserved -> old file + // filename -> new file + ok = STB_TRUE; + + // 'filename -> new file' has always been the goal, so clean up + remove(preserved_old_file); // nothing to be done if it fails + } else { + // couldn't rename, so try renaming preserved file back + + // state is: + // preserved -> old file + // tempname -> new file + stb_rename(preserved_old_file, d->name); + // if the rename failed, there's nothing more we can do + } + } + } else { + // we couldn't get a temp filename. do this the naive way; the worst case failure here + // leaves the filename pointing to nothing and the new file as a tempfile + remove(d->name); + stb_rename(d->temp_name, d->name); + } } } - if (keep == stb_keep_no) - remove(d->temp_name); - free(d->temp_name); free(d->name); free(d); From 747b8d8f71ed5b557234feffa44ff1ed98bed39b Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Thu, 27 Jul 2017 23:51:36 -0500 Subject: [PATCH 06/99] stb_sprintf.h: Don't compare uninitialized value when using zero. This prevents a "Conditional jump or move depends on uninitialised value(s)" error from valgrind when using zero as an argument in line 1045. --- stb_sprintf.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 3828445..abf4371 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -12,6 +12,7 @@ // github:d26435 // github:trex78 // Jari Komppa (SI suffixes) +// Rohit Nirmal // // LICENSE: // @@ -1025,11 +1026,11 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, n64 = 0; } if ((fl & STBSP__TRIPLET_COMMA) == 0) { - while (n) { + do { s -= 2; *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair[(n % 100) * 2]; n /= 100; - } + } while (n); } while (n) { if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { From 923c9c3debf0283c8a025f56174c6305c70392ee Mon Sep 17 00:00:00 2001 From: Benji Smith Date: Mon, 31 Jul 2017 22:22:56 -0700 Subject: [PATCH 07/99] Correct function signature in stbi_write_jpg usage documentation. --- 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 9d553e0..d9ab544 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -35,7 +35,7 @@ USAGE: 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 float *data); - int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data, int quality); 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 2c7b00ac21c8936572c2b036695fc91063c01bb1 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Mon, 7 Aug 2017 14:52:53 +0300 Subject: [PATCH 08/99] Add force_filter and compression_level parameters to (new) `stbi_write_png_to_mem_ex` * `force_filter` being < 0 means the original behavior (i.e. figure out the best-performing filter per scanline); any other values 0 <= x <= 4 correspond to PNG filters (0 = none, 1 = sub, 2 = up, 3 = average, 4 = Paeth). * `compression_level` being < 0 equals `compression_level` 8 (the previous value). The higher this is, the better the compression should be (though it will use more memory). These new parameters are not (yet) exposed for the higher-level API functions. --- stb_image_write.h | 108 ++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 38 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 9d553e0..3d7b3dc 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -910,62 +910,90 @@ 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) +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int x, int y, int n, int filter_type, signed char *line_buffer) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * y; + for (i = 0; i < n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } + } +} + +unsigned char *stbi_write_png_to_mem_ex(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len, int force_filter, int compression_level) { int ctype[5] = { -1, 0, 4, 2, 6 }; unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; unsigned char *out,*o, *filt, *zlib; signed char *line_buffer; - int i,j,k,p,zlen; + int j,zlen; if (stride_bytes == 0) stride_bytes = x * n; + if (force_filter >= 5) { + force_filter = -1; + } + + if (compression_level < 0) { + // TODO: What's the upper limit for compression_level? + compression_level = 8; + } + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } 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 != 0) ? mapping : firstmap; - int best = 0, bestval = 0x7fffffff; - for (p=0; p < 2; ++p) { - 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) - switch (type) { - case 0: line_buffer[i] = z[i]; break; - case 1: line_buffer[i] = z[i]; break; - case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; - case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; - case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; - case 5: line_buffer[i] = z[i]; break; - case 6: line_buffer[i] = z[i]; break; - } - for (i=n; i < x*n; ++i) { - switch (type) { - case 0: line_buffer[i] = z[i]; break; - case 1: line_buffer[i] = z[i] - z[i-n]; break; - case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; - case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; - case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; - case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; - case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; - } - } - if (p) break; - for (i=0; i < x*n; ++i) + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line(pixels, stride_bytes, x, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line(pixels, stride_bytes, x, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { est += abs((signed char) line_buffer[i]); - if (est < bestval) { bestval = est; best = k; } + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line(pixels, stride_bytes, x, j, n, best_filter, line_buffer); + filter_type = best_filter; } } - // when we get here, best contains the filter type, and line_buffer contains the data - filt[j*(x*n+1)] = (unsigned char) best; + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); } STBIW_FREE(line_buffer); - zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, compression_level); STBIW_FREE(filt); if (!zlib) return 0; @@ -1003,6 +1031,10 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in return out; } +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) { + return stbi_write_png_to_mem_ex(pixels, stride_bytes, x, y, n, out_len, -1, -1); +} + #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) { From 7d80a8b44d5a25a922885c84e97bdcaf093195a5 Mon Sep 17 00:00:00 2001 From: Marcin Wojdyr Date: Fri, 11 Aug 2017 00:19:18 +0100 Subject: [PATCH 09/99] avoid GCC7 implicit-fallthrough warning (GCC recognizes certain strings in comments) --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 3828445..d6a00b5 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -927,7 +927,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0; pr = sizeof(void *) * 2; fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros - // drop through to X + // fall through - to X case 'X': // upper hex case 'x': // lower hex From f57bc38ff6e6af67bb7725a030cfa646180d305e Mon Sep 17 00:00:00 2001 From: Dave Butler Date: Fri, 25 Aug 2017 08:02:35 -0900 Subject: [PATCH 10/99] Made some changes to make Clang Happy Someone should double check that that I didn't change the behavior of any of the code. I'm not using most (if any) of the code I touched, just wanted it to compile... --- stb.h | 71 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/stb.h b/stb.h index c1523d1..9727edf 100644 --- a/stb.h +++ b/stb.h @@ -1795,7 +1795,7 @@ STB_EXTERN int stb_prefix (char *s, char *t); 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 const 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); @@ -1822,7 +1822,7 @@ size_t stb_strscpy(char *d, const char *s, size_t n) return len + 1; } -char *stb_plural(int n) +const char *stb_plural(int n) { return n == 1 ? "" : "s"; } @@ -3362,7 +3362,7 @@ unsigned int stb_hashlen(char *str, int len) unsigned int stb_hashptr(void *p) { - unsigned int x = (unsigned int) p; + unsigned int x = (unsigned int)(size_t) p; // typically lacking in low bits and high bits x = stb_rehash(x); @@ -3411,7 +3411,7 @@ unsigned int stb_hash_fast(void *p, int len) if (len <= 0 || q == NULL) return 0; /* Main loop */ - if (((int) q & 1) == 0) { + if (((int)(size_t) q & 1) == 0) { for (;len > 3; len -= 4) { unsigned int val; hash += stb__get16(q); @@ -3737,7 +3737,7 @@ int stb_ischar(char c, char *set) static unsigned char (*tables)[256]; static char ** sets = NULL; - int z = stb_perfect_hash(&p, (int) set); + int z = stb_perfect_hash(&p, (int)(size_t) set); if (z < 0) { int i,k,n,j,f; // special code that means free all existing data @@ -3756,7 +3756,7 @@ int stb_ischar(char c, char *set) tables = (unsigned char (*)[256]) realloc(tables, sizeof(*tables) * k); memset(tables, 0, sizeof(*tables) * k); for (i=0; i < stb_arr_len(sets); ++i) { - k = stb_perfect_hash(&p, (int) sets[i]); + k = stb_perfect_hash(&p, (int)(size_t) sets[i]); assert(k >= 0); n = k >> 3; f = bit[k&7]; @@ -3764,7 +3764,7 @@ int stb_ischar(char c, char *set) tables[n][(unsigned char) sets[i][j]] |= f; } } - z = stb_perfect_hash(&p, (int) set); + z = stb_perfect_hash(&p, (int)(size_t) set); } return tables[z >> 3][(unsigned char) c] & bit[z & 7]; } @@ -7631,14 +7631,14 @@ static stb_ps_hash *stb_ps_makehash(int size, int old_size, void **old_data) h->any_offset = 0; memset(h->table, 0, size * sizeof(h->table[0])); for (i=0; i < old_size; ++i) - if (!stb_ps_empty(old_data[i])) + if (!stb_ps_empty((size_t)old_data[i])) stb_ps_add(EncodeHash(h), old_data[i]); return h; } void stb_ps_delete(stb_ps *ps) { - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: break; case STB_ps_bucket: stb_bucket_free(GetBucket(ps)); break; case STB_ps_array : free(GetArray(ps)); break; @@ -7650,7 +7650,7 @@ stb_ps *stb_ps_copy(stb_ps *ps) { int i; // not a switch: order based on expected performance/power-law distribution - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: return ps; case STB_ps_bucket: { stb_ps_bucket *n = (stb_ps_bucket *) malloc(sizeof(*n)); @@ -7677,8 +7677,8 @@ stb_ps *stb_ps_copy(stb_ps *ps) int stb_ps_find(stb_ps *ps, void *value) { - int i, code = 3 & (int) ps; - assert((3 & (int) value) == STB_ps_direct); + int i, code = 3 & (int)(size_t) ps; + assert((3 & (int)(size_t) value) == STB_ps_direct); assert(stb_ps_fastlist_valid(value)); // not a switch: order based on expected performance/power-law distribution if (code == STB_ps_direct) @@ -7719,11 +7719,11 @@ stb_ps * stb_ps_add (stb_ps *ps, void *value) assert(!stb_ps_find(ps,value)); #endif if (value == NULL) return ps; // ignore NULL adds to avoid bad breakage - assert((3 & (int) value) == STB_ps_direct); + assert((3 & (int)(size_t) value) == STB_ps_direct); assert(stb_ps_fastlist_valid(value)); assert(value != STB_DEL); // STB_DEL is less likely - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: if (ps == NULL) return (stb_ps *) value; return EncodeBucket(stb_bucket_create2(ps,value)); @@ -7772,11 +7772,11 @@ stb_ps * stb_ps_add (stb_ps *ps, void *value) stb_uint32 n = hash & h->mask; void **t = h->table; // find first NULL or STB_DEL entry - if (!stb_ps_empty(t[n])) { + if (!stb_ps_empty((size_t)t[n])) { stb_uint32 s = stb_rehash(hash) | 1; do { n = (n + s) & h->mask; - } while (!stb_ps_empty(t[n])); + } while (!stb_ps_empty((size_t)t[n])); } if (t[n] == STB_DEL) -- h->count_deletes; @@ -7803,9 +7803,9 @@ stb_ps *stb_ps_remove(stb_ps *ps, void *value) #ifdef STB_DEBUG assert(stb_ps_find(ps, value)); #endif - assert((3 & (int) value) == STB_ps_direct); + assert((3 & (int)(size_t) value) == STB_ps_direct); if (value == NULL) return ps; // ignore NULL removes to avoid bad breakage - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: return ps == value ? NULL : ps; case STB_ps_bucket: { @@ -7864,7 +7864,7 @@ stb_ps *stb_ps_remove(stb_ps *ps, void *value) stb_ps_array *a = (stb_ps_array *) malloc(sizeof(*a) + (n-1) * sizeof(a->p[0])); int i,j=0; for (i=0; i < h->size; ++i) - if (!stb_ps_empty(t[i])) + if (!stb_ps_empty((size_t)t[i])) a->p[j++] = t[i]; assert(j == h->count); a->count = j; @@ -7886,7 +7886,7 @@ stb_ps *stb_ps_remove(stb_ps *ps, void *value) stb_ps *stb_ps_remove_any(stb_ps *ps, void **value) { assert(ps != NULL); - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: *value = ps; return NULL; @@ -7919,7 +7919,7 @@ stb_ps *stb_ps_remove_any(stb_ps *ps, void **value) stb_ps_hash *h = GetHash(ps); void **t = h->table; stb_uint32 n = h->any_offset; - while (stb_ps_empty(t[n])) + while (stb_ps_empty((size_t)t[n])) n = (n + 1) & h->mask; *value = t[n]; h->any_offset = (n+1) & h->mask; @@ -7940,7 +7940,7 @@ void ** stb_ps_getlist(stb_ps *ps, int *count) { int i,n=0; void **p = NULL; - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: if (ps == NULL) { *count = 0; return NULL; } p = (void **) malloc(sizeof(*p) * 1); @@ -7966,7 +7966,7 @@ void ** stb_ps_getlist(stb_ps *ps, int *count) stb_ps_hash *h = GetHash(ps); p = (void **) malloc(sizeof(*p) * h->count); for (i=0; i < h->size; ++i) - if (!stb_ps_empty(h->table[i])) + if (!stb_ps_empty((size_t)h->table[i])) p[n++] = h->table[i]; break; } @@ -7978,7 +7978,7 @@ void ** stb_ps_getlist(stb_ps *ps, int *count) int stb_ps_writelist(stb_ps *ps, void **list, int size ) { int i,n=0; - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: if (ps == NULL || size <= 0) return 0; list[0] = ps; @@ -8000,7 +8000,7 @@ int stb_ps_writelist(stb_ps *ps, void **list, int size ) stb_ps_hash *h = GetHash(ps); if (size <= 0) return 0; for (i=0; i < h->count; ++i) { - if (!stb_ps_empty(h->table[i])) { + if (!stb_ps_empty((size_t)h->table[i])) { list[n++] = h->table[i]; if (n == size) break; } @@ -8014,7 +8014,7 @@ int stb_ps_writelist(stb_ps *ps, void **list, int size ) int stb_ps_enum(stb_ps *ps, void *data, int (*func)(void *value, void *data)) { int i; - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: if (ps == NULL) return STB_TRUE; return func(ps, data); @@ -8036,7 +8036,7 @@ int stb_ps_enum(stb_ps *ps, void *data, int (*func)(void *value, void *data)) case STB_ps_hash: { stb_ps_hash *h = GetHash(ps); for (i=0; i < h->count; ++i) - if (!stb_ps_empty(h->table[i])) + if (!stb_ps_empty((size_t)h->table[i])) if (!func(h->table[i], data)) return STB_FALSE; return STB_TRUE; @@ -8047,7 +8047,7 @@ int stb_ps_enum(stb_ps *ps, void *data, int (*func)(void *value, void *data)) int stb_ps_count (stb_ps *ps) { - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: return ps != NULL; case STB_ps_bucket: { @@ -8071,7 +8071,7 @@ void ** stb_ps_fastlist(stb_ps *ps, int *count) { static void *storage; - switch (3 & (int) ps) { + switch (3 & (int)(size_t) ps) { case STB_ps_direct: if (ps == NULL) { *count = 0; return NULL; } storage = ps; @@ -9118,7 +9118,7 @@ static void stb__add_epsilon(stb_matcher *matcher, int from, int to) static void stb__add_edge(stb_matcher *matcher, int from, int to, int type) { - stb_nfa_edge z = { type, to }; + stb_nfa_edge z = { (stb_int16)type, (stb_uint16)to }; if (matcher->nodes[from].out == NULL) stb_arr_malloc((void **) &matcher->nodes[from].out, matcher); stb_arr_push(matcher->nodes[from].out, z); @@ -9831,7 +9831,7 @@ int stb_regex(char *regex, char *str) static char ** regexps; static char ** regexp_cache; static unsigned short *mapping; - int z = stb_perfect_hash(&p, (int) regex); + int z = stb_perfect_hash(&p, (int)(size_t) regex); if (z >= 0) { if (strcmp(regex, regexp_cache[(int) mapping[z]])) { int i = mapping[z]; @@ -9862,8 +9862,8 @@ int stb_regex(char *regex, char *str) n = stb_perfect_create(&p, (unsigned int *) (char **) regexps, stb_arr_len(regexps)); mapping = (unsigned short *) realloc(mapping, n * sizeof(*mapping)); for (i=0; i < stb_arr_len(regexps); ++i) - mapping[stb_perfect_hash(&p, (int) regexps[i])] = i; - z = stb_perfect_hash(&p, (int) regex); + mapping[stb_perfect_hash(&p, (int)(size_t) regexps[i])] = i; + z = stb_perfect_hash(&p, (int)(size_t) regex); } return stb_matcher_find(matchers[(int) mapping[z]], str); } @@ -10357,7 +10357,7 @@ static void stb__write(unsigned char v) ++stb__outbytes; } -#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v))) +#define stb_out(v) (stb__out ? (void)(*stb__out++ = (stb_uchar) (v)) : stb__write((stb_uchar) (v))) static void stb_out2(stb_uint v) { @@ -10620,7 +10620,8 @@ static size_t stb_out_backpatch_id(void) static void stb_out_backpatch(size_t id, stb_uint value) { - stb_uchar data[4] = { value >> 24, value >> 16, value >> 8, value }; + + stb_uchar data[4] = { (stb_uchar)(value >> 24), (stb_uchar)(value >> 16), (stb_uchar)(value >> 8), (stb_uchar)(value) }; if (stb__out) { memcpy((void *) id, data, 4); } else { From 2545eee3efcc6ebb6c81857664559f1cf2ba262a Mon Sep 17 00:00:00 2001 From: Dave Butler Date: Fri, 25 Aug 2017 08:24:58 -0900 Subject: [PATCH 11/99] Added myself as a contributor for the pull request --- stb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb.h b/stb.h index 9727edf..8e73781 100644 --- a/stb.h +++ b/stb.h @@ -193,6 +193,7 @@ CREDITS Eugene Opalev Tim Sjostrand github:infatum + Dave Butler (Croepha) */ #include From c8245bbf22aa2cf9056b346ab56ab4ee525a2905 Mon Sep 17 00:00:00 2001 From: Jonathan Adamczewski Date: Mon, 28 Aug 2017 23:13:39 -0700 Subject: [PATCH 12/99] Remove arg from memset macro My clang doesn't like the macro defined this way, choking at the callsite on line 195 with "too many arguments provided to function-like macro invocation" This change matches what is done for STBTT_memset in stb_truetype.h --- stb_dxt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_dxt.h b/stb_dxt.h index b53aca7..6504325 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -88,7 +88,7 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr #ifndef STBD_MEMSET #include -#define STBD_MEMSET(x) memset(x) +#define STBD_MEMSET memset #endif static unsigned char stb__Expand5[32]; From c06c9fe6bc907d58cb252be781373393999613ba Mon Sep 17 00:00:00 2001 From: lieff Date: Thu, 31 Aug 2017 19:33:28 +0300 Subject: [PATCH 13/99] place const tables to protected .rdata section --- stb_image.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stb_image.h b/stb_image.h index a056138..031cb47 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1790,7 +1790,7 @@ static void stbi__grow_buffer_unsafe(stbi__jpeg *j) } // (1 << n) - 1 -static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; // decode a jpeg huffman value from the bitstream stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) @@ -1843,7 +1843,7 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) } // bias[n] = (-1<rgb = 0; for (i=0; i < s->img_n; ++i) { - static unsigned char rgb[3] = { 'R', 'G', 'B' }; + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) ++z->rgb; @@ -3912,18 +3912,18 @@ static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room return 1; } -static int stbi__zlength_base[31] = { +static const int stbi__zlength_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; -static int stbi__zlength_extra[31]= +static const int stbi__zlength_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; -static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; -static int stbi__zdist_extra[32] = +static const int stbi__zdist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; static int stbi__parse_huffman_block(stbi__zbuf *a) @@ -3970,7 +3970,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) static int stbi__compute_huffman_codes(stbi__zbuf *a) { - static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; stbi__zhuffman z_codelength; stbi_uc lencodes[286+32+137];//padding for maximum single op stbi_uc codelength_sizes[19]; @@ -4229,7 +4229,7 @@ static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) static int stbi__check_png_header(stbi__context *s) { - static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; int i; for (i=0; i < 8; ++i) if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); @@ -4275,7 +4275,7 @@ static int stbi__paeth(int a, int b, int c) return c; } -static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; // 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) From 350173026a2b5296656d158267c81ee2a38ed90c Mon Sep 17 00:00:00 2001 From: Mikhail Morozov Date: Fri, 1 Sep 2017 02:06:06 +0300 Subject: [PATCH 14/99] stb_image: support for 1-bit BMP --- stb_image.h | 55 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/stb_image.h b/stb_image.h index a056138..6141a7f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5007,7 +5007,6 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) } if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); 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"); @@ -5125,29 +5124,47 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req pal[i][3] = 255; } stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); - if (info.bpp == 4) width = (s->img_x + 1) >> 1; + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else 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 (info.bpp == 4) { - v2 = v & 15; - v >>= 4; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } } - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - if (i+1 == (int) s->img_x) break; - v = (info.bpp == 8) ? stbi__get8(s) : v2; - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; + stbi__skip(s, pad); + } + } else { + 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 (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); } - stbi__skip(s, pad); } } else { int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; From b6b43df18635ccdb128f5c3708d2ae640f647ef4 Mon Sep 17 00:00:00 2001 From: darealshinji Date: Mon, 4 Sep 2017 14:01:43 +0200 Subject: [PATCH 15/99] Use stbi__mad4sizes_valid() only if STBI_NO_LINEAR or STBI_NO_HDR are defined --- stb_image.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index a056138..87ba98a 100644 --- a/stb_image.h +++ b/stb_image.h @@ -503,7 +503,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch #include #include -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#if !defined(STBI_NO_LINEAR) && !defined(STBI_NO_HDR) #include // ldexp #endif @@ -893,11 +893,13 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add) } // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) && !defined(STBI_NO_HDR) 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); } +#endif // mallocs with size overflow checking static void *stbi__malloc_mad2(int a, int b, int add) @@ -912,11 +914,13 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add) return stbi__malloc(a*b*c + add); } +#if !defined(STBI_NO_LINEAR) && !defined(STBI_NO_HDR) 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); } +#endif // stbi__err - error // stbi__errpf - error returning pointer to float From 84fd09ea5383262c1993ab52981ad3a3186ee15b Mon Sep 17 00:00:00 2001 From: Dougall Johnson Date: Sat, 14 Oct 2017 11:58:03 +1100 Subject: [PATCH 16/99] stb_truetype: Fix sign error in CFF push immediate --- stb_truetype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_truetype.h b/stb_truetype.h index cec2425..6a6e584 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -2172,7 +2172,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st // push immediate if (b0 == 255) { - f = (float)stbtt__buf_get32(&b) / 0x10000; + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; } else { stbtt__buf_skip(&b, -1); f = (float)(stbtt_int16)stbtt__cff_int(&b); From 1f2b4271e3d6c4abc143d15ae4be6a47685f230b Mon Sep 17 00:00:00 2001 From: Dougall Johnson Date: Sat, 14 Oct 2017 11:59:09 +1100 Subject: [PATCH 17/99] stb_truetype: Fix CFF GetGlyphBox optional params Fixes #404 --- stb_truetype.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 6a6e584..0cb2fdc 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -2210,12 +2210,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in { 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; - } + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; return r ? c.num_vertices : 0; } From a981af59c5af476c2784ee101f9522a2c51272ae Mon Sep 17 00:00:00 2001 From: Aldo Culquicondor Date: Mon, 16 Oct 2017 12:30:27 -0500 Subject: [PATCH 18/99] Fix tests compilation --- stb_tilemap_editor.h | 4 ++-- tests/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 94cff66..352042b 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1847,7 +1847,7 @@ static int stbte__minibutton(int colormode, int x, int y, int ch, int id) int x0 = x, y0 = y, x1 = x+8, y1 = y+7; int over = stbte__hittest(x0,y0,x1,y1,id); if (stbte__ui.event == STBTE__paint) { - char str[2] = { ch,0 }; + char str[2] = { (char)ch, 0 }; stbte__draw_textbox(x0,y0,x1,y1, str,1,0,colormode, STBTE__INDEX_FOR_ID(id,0,0)); } return stbte__button_core(id); @@ -1858,7 +1858,7 @@ static int stbte__layerbutton(int x, int y, int ch, int id, int toggled, int dis int x0 = x, y0 = y, x1 = x+10, y1 = y+11; int over = !disabled && stbte__hittest(x0,y0,x1,y1,id); if (stbte__ui.event == STBTE__paint) { - char str[2] = { ch,0 }; + char str[2] = { (char)ch, 0 }; int off = (9-stbte__get_char_width(ch))/2; stbte__draw_textbox(x0,y0,x1,y1, str, off+1,2, colormode, STBTE__INDEX_FOR_ID(id,disabled,toggled)); } diff --git a/tests/Makefile b/tests/Makefile index 055ffaf..53e2485 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,5 +3,5 @@ CFLAGS = -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -DSTB_DIVIDE_TEST CPPFLAGS = -Wno-write-strings -DSTB_DIVIDE_TEST all: - $(CC) $(INCLUDES) $(CFLAGS) ../stb_vorbis.c test_c_compilation.c -lm - $(CC) $(INCLUDES) $(CPPFLAGS) test_cpp_compilation.cpp -lm + $(CC) $(INCLUDES) $(CFLAGS) ../stb_vorbis.c test_c_compilation.c -lm + $(CC) $(INCLUDES) $(CPPFLAGS) test_cpp_compilation.cpp -lm -lstdc++ From 5182622b1442c4e21e5e9b921a3a7b474ca3f9b1 Mon Sep 17 00:00:00 2001 From: Kenney Phillis Jr Date: Sat, 4 Nov 2017 03:28:03 -0500 Subject: [PATCH 19/99] tests: fix test_trutype.c on msvc 2015 This is 3 short fixes for the file test_truetype.c. 1. Fix the Visual Studio Secure CRT Errors by defining _CRT_SECURE_NO_WARNINGS 2. Fix signed/unsigned Character conversion warning/error. 3. Fix the Definitions for the Image packer. This now works as intended generating usable png files. --- tests/test_truetype.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/test_truetype.c b/tests/test_truetype.c index d18d3b5..b432fd4 100644 --- a/tests/test_truetype.c +++ b/tests/test_truetype.c @@ -1,13 +1,20 @@ +#ifndef _CRT_SECURE_NO_WARNINGS +// Fixes Compile Errors for Visual Studio 2005 or newer + #define _CRT_SECURE_NO_WARNINGS +#endif + +#define STB_RECT_PACK_IMPLEMENTATION #include "stb_rect_pack.h" #define STB_TRUETYPE_IMPLEMENTATION #include "stb_truetype.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" #ifdef TT_TEST #include -char ttf_buffer[1<<25]; +unsigned char ttf_buffer[1 << 25]; unsigned char output[512*100]; void debug(void) @@ -66,12 +73,14 @@ int main(int argc, char **argv) stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL); pr[0].chardata_for_range = pdata; - pr[0].first_unicode_char_in_range = 32; - pr[0].num_chars_in_range = 95; + pr[0].array_of_unicode_codepoints = NULL; + pr[0].first_unicode_codepoint_in_range = 32; + pr[0].num_chars = 95; pr[0].font_size = 20.0f; pr[1].chardata_for_range = pdata+256; - pr[1].first_unicode_char_in_range = 0xa0; - pr[1].num_chars_in_range = 0x100 - 0xa0; + pr[1].array_of_unicode_codepoints = NULL; + pr[1].first_unicode_codepoint_in_range = 0xa0; + pr[1].num_chars = 0x100 - 0xa0; pr[1].font_size = 20.0f; stbtt_PackSetOversampling(&pc, 2, 2); From 6e50ac78602bf441dd6136ecf6a5004e309d5109 Mon Sep 17 00:00:00 2001 From: Kenney Phillis Jr Date: Sat, 4 Nov 2017 03:35:02 -0500 Subject: [PATCH 20/99] stb_truetype: Fix undefined function warning This fixes the error in bug report #516. This should work as intended since the function definitions line up. --- stb_truetype.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stb_truetype.h b/stb_truetype.h index cec2425..5a191d6 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -3318,6 +3318,11 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo * return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); } +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); From 9dfa8c7f31032644db68e5c756667d41ef5e904a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=ABl=20Seghezzi?= Date: Fri, 24 Nov 2017 13:44:39 +0100 Subject: [PATCH 21/99] return comp info in bytes (support for 16 bit images) --- stb_image.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index a056138..193ada1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4902,7 +4902,7 @@ static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) } if (x) *x = p->s->img_x; if (y) *y = p->s->img_y; - if (comp) *comp = p->s->img_n; + if (comp) *comp = p->s->img_n * p->depth / 8; return 1; } @@ -6667,7 +6667,7 @@ 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, dummy; + int channelCount, dummy, depth; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; @@ -6687,7 +6687,8 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) } *y = stbi__get32be(s); *x = stbi__get32be(s); - if (stbi__get16be(s) != 8) { + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { stbi__rewind( s ); return 0; } @@ -6695,7 +6696,7 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) stbi__rewind( s ); return 0; } - *comp = 4; + *comp = 4 * depth / 8; return 1; } #endif From 4c1a786455523f9805816dfc9b40df4133988f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=ABl=20Seghezzi?= Date: Fri, 24 Nov 2017 14:35:14 +0100 Subject: [PATCH 22/99] Revert "return comp info in bytes (support for 16 bit images)" This reverts commit 9dfa8c7f31032644db68e5c756667d41ef5e904a. --- stb_image.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stb_image.h b/stb_image.h index 193ada1..a056138 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4902,7 +4902,7 @@ static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) } if (x) *x = p->s->img_x; if (y) *y = p->s->img_y; - if (comp) *comp = p->s->img_n * p->depth / 8; + if (comp) *comp = p->s->img_n; return 1; } @@ -6667,7 +6667,7 @@ 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, dummy, depth; + int channelCount, dummy; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; @@ -6687,8 +6687,7 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) } *y = stbi__get32be(s); *x = stbi__get32be(s); - depth = stbi__get16be(s); - if (depth != 8 && depth != 16) { + if (stbi__get16be(s) != 8) { stbi__rewind( s ); return 0; } @@ -6696,7 +6695,7 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) stbi__rewind( s ); return 0; } - *comp = 4 * depth / 8; + *comp = 4; return 1; } #endif From fcf0b9960197e83a73d32c4931239bf558125d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=ABl=20Seghezzi?= Date: Fri, 24 Nov 2017 14:36:37 +0100 Subject: [PATCH 23/99] add stbi_is_16 --- stb_image.h | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index a056138..a4dc1c1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -416,11 +416,14 @@ STBIDEF void stbi_image_free (void *retval_from_stbi_load); // get image dimensions & components without fully decoding STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_from_callbacks(stbi_io_callbacks const *clbk, void *user); #ifndef STBI_NO_STDIO STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); - +STBIDEF int stbi_is_16 (char const *filename); +STBIDEF int stbi_is_16_from_file (FILE *f); #endif @@ -784,6 +787,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__png_test(stbi__context *s); 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); +static int stbi__png_is16(stbi__context *s); #endif #ifndef STBI_NO_BMP @@ -802,6 +806,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); 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, int bpc); static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); #endif #ifndef STBI_NO_HDR @@ -4912,6 +4917,19 @@ static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) p.s = s; return stbi__png_info_raw(&p, x, y, comp); } + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} #endif // Microsoft/Windows BMP image @@ -6667,7 +6685,7 @@ 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, dummy; + int channelCount, dummy, depth; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; @@ -6687,7 +6705,8 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) } *y = stbi__get32be(s); *x = stbi__get32be(s); - if (stbi__get16be(s) != 8) { + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { stbi__rewind( s ); return 0; } @@ -6698,6 +6717,33 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) *comp = 4; return 1; } + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, dummy, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + dummy = stbi__get32be(s); + dummy = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} #endif #ifndef STBI_NO_PIC @@ -6928,6 +6974,19 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) return stbi__err("unknown image type", "Image not of any known type, or corrupt"); } +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + #ifndef STBI_NO_STDIO STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) { @@ -6949,6 +7008,27 @@ STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) fseek(f,pos,SEEK_SET); return r; } + +STBIDEF int stbi_is_16(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} #endif // !STBI_NO_STDIO STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) @@ -6965,6 +7045,20 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int return stbi__info_main(&s,x,y,comp); } +STBIDEF int stbi_is_16_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + #endif // STB_IMAGE_IMPLEMENTATION /* From 4bffebc5f0f1b69e1ce579cfffc24cc62c07dd08 Mon Sep 17 00:00:00 2001 From: Julian Raschke Date: Sat, 25 Nov 2017 17:23:33 +0800 Subject: [PATCH 24/99] Avoid warning about unused stbi__float_postprocess --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index a056138..0e8ac15 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1103,7 +1103,7 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, return (stbi__uint16 *) result; } -#ifndef STBI_NO_HDR +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) { if (stbi__vertically_flip_on_load && result != NULL) { From 87a3143fb4ca2111d77b27edda2b91ae493cc9a5 Mon Sep 17 00:00:00 2001 From: Chris Forseth Date: Mon, 27 Nov 2017 22:41:51 -0600 Subject: [PATCH 25/99] GIF Loading - multiple frames; - Allow loading a gif as multiple frames into a single buffer. Each frame is a full image seperated by a (w * h * comp) stride. - Optionally, can pass in a pointer to a int, which will be filled with an array layers long contain ms for each frame. - Fix gif's not loading the initial transparent background - I believe also fix disposal rules for subsequent frames (though being somewhat inefficient with memory to do so) - Add a flip_vertical that takes into account slices as well. Compiled using VS2017, but nothing else as I'm not really setup for it. Apologies. --- stb_image.h | 296 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 217 insertions(+), 79 deletions(-) diff --git a/stb_image.h b/stb_image.h index a056138..aa25fb2 100644 --- a/stb_image.h +++ b/stb_image.h @@ -353,6 +353,10 @@ typedef struct 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_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + #ifndef STBI_NO_STDIO STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); @@ -819,6 +823,7 @@ static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); #ifndef STBI_NO_GIF static int stbi__gif_test(stbi__context *s); static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); #endif @@ -1054,6 +1059,18 @@ static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) } } +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} + static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; @@ -1205,6 +1222,21 @@ STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *u return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + + unsigned char *result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + #ifndef STBI_NO_LINEAR static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { @@ -6038,11 +6070,13 @@ typedef struct typedef struct { int w,h; - stbi_uc *out, *old_out; // output buffer (always 4 components) - int flags, bgindex, ratio, transparent, eflags, delay; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; stbi_uc pal[256][4]; stbi_uc lpal[256][4]; - stbi__gif_lzw codes[4096]; + stbi__gif_lzw codes[8192]; stbi_uc *color_table; int parse, step; int lflags; @@ -6050,6 +6084,7 @@ typedef struct int max_x, max_y; int cur_x, cur_y; int line_size; + int delay; } stbi__gif; static int stbi__gif_test_raw(stbi__context *s) @@ -6125,6 +6160,7 @@ static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) { stbi_uc *p, *c; + int idx; // recurse to decode the prefixes, since the linked-list is backwards, // and working backwards through an interleaved image would be nasty @@ -6133,10 +6169,12 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) if (g->cur_y >= g->max_y) return; - p = &g->out[g->cur_x + g->cur_y]; - c = &g->color_table[g->codes[code].suffix * 4]; + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; - if (c[3] >= 128) { + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; p[0] = c[2]; p[1] = c[1]; p[2] = c[0]; @@ -6210,11 +6248,16 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) stbi__skip(s,len); return g->out; } else if (code <= avail) { - if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } if (oldcode >= 0) { p = &g->codes[avail++]; - if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + p->prefix = (stbi__int16) oldcode; p->first = g->codes[oldcode].first; p->suffix = (code == avail) ? p->first : g->codes[code].first; @@ -6236,62 +6279,72 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) } } -static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1) -{ - int x, y; - stbi_uc *c = g->pal[g->bgindex]; - 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; - } - } -} - // this function is designed to support animated gifs, although stb_image doesn't support it -static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) -{ - int i; - stbi_uc *prev_out = 0; - - 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"); +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 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); + g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->history = (stbi_uc *) stbi__malloc(g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "tranparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to teh color that was there the previous frame. + memset( g->out, 0x00, 4 * g->w * g->h ); + memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent) + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; - prev_out = g->out; - g->out = (stbi_uc *) stbi__malloc_mad3(4, g->w, g->h, 0); - if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + if ((dispose == 4) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } - 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); + if (dispose == 4) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } } - break; + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose? Same as 4? + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); } + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + for (;;) { - switch (stbi__get8(s)) { + int tag = stbi__get8(s); + switch (tag) { case 0x2C: /* Image Descriptor */ { - int prev_trans = -1; stbi__int32 x, y, w, h; stbi_uc *o; @@ -6324,19 +6377,24 @@ 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) { - 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"); - + return stbi__errpuc("missing color table", "Corrupt GIF"); + o = stbi__process_gif_raster(s, g); if (o == NULL) return NULL; - if (prev_trans != -1) - g->pal[g->transparent][3] = (stbi_uc) prev_trans; + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex >= 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } return o; } @@ -6344,19 +6402,35 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i case 0x21: // Comment Extension. { int len; - if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. len = stbi__get8(s); if (len == 4) { g->eflags = stbi__get8(s); - g->delay = stbi__get16le(s); - g->transparent = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } } else { stbi__skip(s, len); break; } - } - while ((len = stbi__get8(s)) != 0) + } + while ((len = stbi__get8(s)) != 0) { stbi__skip(s, len); + } break; } @@ -6367,28 +6441,92 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i return stbi__errpuc("unknown code", "Corrupt GIF"); } } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } - STBI_NOTUSED(req_comp); + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != nullptr); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } } 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); + stbi__gif g; + 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, 0); 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; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. 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); - STBI_FREE(g); + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + return u; } From 28c28b0bd23534f405938e29505fb47780fadd3d Mon Sep 17 00:00:00 2001 From: Chris Forseth Date: Mon, 27 Nov 2017 23:06:53 -0600 Subject: [PATCH 26/99] Per the contributor doc - added my name. Noticed urraka also did some work here, so hopefully didn't step on any toes. - Fix an issue where the spec of the gif for restore to previous uses code 3, not 4. - To get results that worked - made an assumption that "clear to background" meant "revert back to what was there before I drew", where mode 1 would revert back to the previous frame [slightly different]. If I clear to background color instead, I ended up with large opaque squares in gifs that changes their transparent colour each frame. - Background color is supposed to be used only for pixels not rendered by the image, so took that to mean it only really affected the previous frame, or potentially any frame that used full disposal. Since background color is allowed to be unspecified this is what lead me to believe I shouldn't use it for disposal. - Oh, also upped the codes table to 8192 as 4096 ended up being too small for a few of my test cases. Full disclaimer - I only read through the GIF format for this contribution, so competly could be misinterpreting the spec - but this gave me reuslts that matched Chrome. --- stb_image.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index aa25fb2..167904f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -74,7 +74,7 @@ RECENT REVISION HISTORY: Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) github:urraka (animated gif) Junggon Kim (PNM comments) - Daniel Gibson (16-bit TGA) + github:tocchan (animated gif) Daniel Gibson (16-bit TGA) socks-the-fox (16-bit PNG) Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes @@ -6313,7 +6313,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i dispose = 2; // if I don't have an image to revert back to, default to the old background } - if (dispose == 4) { // use previous graphic + if (dispose == 3) { // use previous graphic for (pi = 0; pi < pcount; ++pi) { if (g->history[pi]) { memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); @@ -6329,7 +6329,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i } else { // This is a non-disposal case eithe way, so just // leave the pixels as is, and they will become the new background - // 1: do not dispose? Same as 4? + // 1: do not dispose // 0: not specified. } From 03b4bbc5d2d51831baf6359c9527a1733de74cdd Mon Sep 17 00:00:00 2001 From: Chris Forseth Date: Mon, 27 Nov 2017 23:32:44 -0600 Subject: [PATCH 27/99] Fix a disposal flag mistype. Only clear to background color if index is non-zero. Fixed a the disposal test gif I was using - now renders properly (gif has no transparent set, but all renderers still considered it transparent. Spec says 0 should be ignored if 0, but was confusing by saying it only in the context of the pal not existing.. but seems to be the case always. --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 167904f..4c297cc 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6309,7 +6309,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i dispose = (g->eflags & 0x1C) >> 2; pcount = g->w * g->h; - if ((dispose == 4) && (two_back == 0)) { + if ((dispose == 3) && (two_back == 0)) { dispose = 2; // if I don't have an image to revert back to, default to the old background } @@ -6386,7 +6386,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i // if this was the first frame, pcount = g->w * g->h; - if (first_frame && (g->bgindex >= 0)) { + if (first_frame && (g->bgindex > 0)) { // if first frame, any pixel not drawn to gets the background color for (pi = 0; pi < pcount; ++pi) { if (g->history[pi] == 0) { From de75509b1c35f6d8a03c341364600922391d6b94 Mon Sep 17 00:00:00 2001 From: Chris Forseth Date: Mon, 27 Nov 2017 23:42:13 -0600 Subject: [PATCH 28/99] Remove a nullptr --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 4c297cc..4d6b959 100644 --- a/stb_image.h +++ b/stb_image.h @@ -6487,7 +6487,7 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, (*delays)[layers - 1U] = g.delay; } } - } while (u != nullptr); + } while (u != 0); // free temp buffer; STBI_FREE(g.out); From 3a969eb64c46326490f7307b834c71b601204b99 Mon Sep 17 00:00:00 2001 From: Marcin Wojdyr Date: Thu, 7 Dec 2017 15:30:43 +0000 Subject: [PATCH 29/99] remove duplicated `pr = 0` avoid warning: Variable 'pr' is reassigned a value before the old one has been used caused by: fw = pr = fl = 0; ... pr = 0; --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 3828445..5d87b1a 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -1259,7 +1259,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, s = num + STBSP__NUMSZ - 1; *s = f[0]; l = 1; - fw = pr = fl = 0; + fw = fl = 0; lead[0] = 0; tail[0] = 0; pr = 0; From 5c2c826df9d8cc50df4eae1b6c807ef8d194848c Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 24 Dec 2017 13:57:03 -0500 Subject: [PATCH 30/99] stb_truetype: Silence warnings of winding_lengths Coverty scan shows potential warnings of winding_lengths. Forcing it to be a NULL fixes the issue. --- stb_truetype.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index cec2425..9eec983 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -3229,8 +3229,9 @@ error: STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); From 5e844ffe70ca88fe56777e73c4fe50b24cb722bd Mon Sep 17 00:00:00 2001 From: John Tullos Date: Mon, 1 Jan 2018 18:08:30 -0600 Subject: [PATCH 31/99] Using secure versions of CRT calls to avoid Microsoft Visual C/C++ compiler errors/warnings. --- stb_image_write.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 9d553e0..17f9f3f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -230,7 +230,12 @@ static void stbi__stdio_write(void *context, void *data, int size) static int stbi__start_write_file(stbi__write_context *s, const char *filename) { - FILE *f = fopen(filename, "wb"); + FILE *f; +#ifdef _MSC_VER + fopen_s(&f, filename, "wb"); +#else + f = fopen(filename, "wb"); +#endif stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); return f != NULL; } @@ -626,7 +631,11 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; s->func(s->context, header, sizeof(header)-1); +#ifdef _MSC_VER + len = sprintf_s(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif s->func(s->context, buffer, len); for(i=0; i < y; i++) @@ -1010,7 +1019,11 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const int len; unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (png == NULL) return 0; +#ifdef _MSC_VER + fopen_s(&f, filename, "wb"); +#else f = fopen(filename, "wb"); +#endif if (!f) { STBIW_FREE(png); return 0; } fwrite(png, 1, len, f); fclose(f); From 32a7d5ab68bd35455b24aa852d6d6b7d0f55b494 Mon Sep 17 00:00:00 2001 From: John Tullos Date: Mon, 1 Jan 2018 18:54:26 -0600 Subject: [PATCH 32/99] Added STBI_MSC_SECURE_CRT to support newer MSVC compilers as optional For issue #533 --- stb_image_write.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 17f9f3f..b977440 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -10,6 +10,11 @@ Will probably not work correctly with strict-aliasing optimizations. + If using a modern Microsoft Compiler non-safe versions of CRT calls may cause + compilation warnings or even errors. To avoid this, aldo before #including, + + #define STBI_MSC_SECURE_CRT + ABOUT: This header file is a library for writing images to C stdio. It could be @@ -231,7 +236,7 @@ static void stbi__stdio_write(void *context, void *data, int size) static int stbi__start_write_file(stbi__write_context *s, const char *filename) { FILE *f; -#ifdef _MSC_VER +#ifdef STBI_MSC_SECURE_CRT fopen_s(&f, filename, "wb"); #else f = fopen(filename, "wb"); @@ -631,7 +636,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; s->func(s->context, header, sizeof(header)-1); -#ifdef _MSC_VER +#ifdef STBI_MSC_SECURE_CRT len = sprintf_s(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); #else len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); @@ -1019,7 +1024,7 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const int len; unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (png == NULL) return 0; -#ifdef _MSC_VER +#ifdef STBI_MSC_SECURE_CRT fopen_s(&f, filename, "wb"); #else f = fopen(filename, "wb"); From eb17d8a6dd32a7b6ce8f345c75505df423be071a Mon Sep 17 00:00:00 2001 From: John Tullos Date: Mon, 1 Jan 2018 18:56:36 -0600 Subject: [PATCH 33/99] Fixed grammar, spelling issues in comments --- stb_image_write.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index b977440..2e644cf 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -10,8 +10,8 @@ Will probably not work correctly with strict-aliasing optimizations. - If using a modern Microsoft Compiler non-safe versions of CRT calls may cause - compilation warnings or even errors. To avoid this, aldo before #including, + If using a modern Microsoft Compiler, non-safe versions of CRT calls may cause + compilation warnings or even errors. To avoid this, also before #including, #define STBI_MSC_SECURE_CRT From 841862a6225c891d32d194267ba4b81f1499755a Mon Sep 17 00:00:00 2001 From: John Tullos Date: Mon, 1 Jan 2018 18:56:36 -0600 Subject: [PATCH 34/99] Fixed grammar, spelling issues in comments issue #533 --- stb_image_write.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index b977440..2e644cf 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -10,8 +10,8 @@ Will probably not work correctly with strict-aliasing optimizations. - If using a modern Microsoft Compiler non-safe versions of CRT calls may cause - compilation warnings or even errors. To avoid this, aldo before #including, + If using a modern Microsoft Compiler, non-safe versions of CRT calls may cause + compilation warnings or even errors. To avoid this, also before #including, #define STBI_MSC_SECURE_CRT From 244d83bc3d859293f55812d48b3db168e581f6ab Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 02:23:18 -0800 Subject: [PATCH 35/99] fix unchecked length in stb_vorbis that could crash on corrupt/invalid files --- stb_vorbis.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 14cebbf..49829d2 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3,9 +3,9 @@ // // Original version written by Sean Barrett in 2007. // -// Originally sponsored by RAD Game Tools. Seeking sponsored -// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software, -// Aras Pranckevicius, and Sean Barrett. +// Originally sponsored by RAD Game Tools. Seeking implementation +// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker, +// Elias Software, Aras Pranckevicius, and Sean Barrett. // // LICENSE // @@ -32,6 +32,7 @@ // manxorist@github saga musix github:infatum // // Partial history: +// 1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files // 1.11 - 2017/07/23 - fix MinGW compilation // 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 @@ -2042,6 +2043,8 @@ static int residue_decode(vorb *f, Codebook *book, float *target, int offset, in return TRUE; } +// n is 1/2 of the blocksize -- +// specification: "Correct per-vector decode length is [n]/2" static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) { int i,j,pass; @@ -2049,7 +2052,10 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int rtype = f->residue_types[rn]; int c = r->classbook; int classwords = f->codebooks[c].dimensions; - int n_read = r->end - r->begin; + unsigned int actual_size = rtype == 2 ? n*2 : n; + unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size); + unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size); + int n_read = limit_r_end - limit_r_begin; int part_read = n_read / r->part_size; int temp_alloc_point = temp_alloc_save(f); #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE @@ -4077,7 +4083,10 @@ static int start_decoder(vorb *f) 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; + unsigned int actual_size = f->blocksize_1 / 2; + unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size; + unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size; + int n_read = limit_r_end - limit_r_begin; int part_read = n_read / r->part_size; if (part_read > max_part_read) max_part_read = part_read; @@ -4088,6 +4097,8 @@ static int start_decoder(vorb *f) classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); #endif + // maximum reasonable partition size is f->blocksize_1 + f->temp_memory_required = classify_mem; if (imdct_mem > f->temp_memory_required) f->temp_memory_required = imdct_mem; @@ -5351,6 +5362,8 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files + 1.11 - 2017/07/23 - fix MinGW compilation 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; From 68f857727cd602e636ebf825ec3a47e42dc42b44 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 02:24:05 -0800 Subject: [PATCH 36/99] add stb_ucharcmp to stb.h --- stb.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stb.h b/stb.h index c1523d1..cbbe425 100644 --- a/stb.h +++ b/stb.h @@ -1,4 +1,4 @@ -/* stb.h - v2.30 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h +/* stb.h - v2.31 - 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.31 stb_ucharcmp 2.30 MinGW fix 2.29 attempt to fix use of swprintf() 2.28 various new functionality @@ -1548,7 +1549,7 @@ STB_EXTERN int (*stb_doublecmp(int offset))(const void *a, const void *b); STB_EXTERN int (*stb_charcmp(int offset))(const void *a, const void *b); #ifdef STB_DEFINE -static int stb__intcmpoffset, stb__charcmpoffset, stb__strcmpoffset; +static int stb__intcmpoffset, stb__ucharcmpoffset, stb__strcmpoffset; static int stb__floatcmpoffset, stb__doublecmpoffset; int stb__intcmp(const void *a, const void *b) @@ -1558,10 +1559,10 @@ int stb__intcmp(const void *a, const void *b) return p < q ? -1 : p > q; } -int stb__charcmp(const void *a, const void *b) +int stb__ucharcmp(const void *a, const void *b) { - const int p = *(const unsigned char *) ((const char *) a + stb__charcmpoffset); - const int q = *(const unsigned char *) ((const char *) b + stb__charcmpoffset); + const int p = *(const unsigned char *) ((const char *) a + stb__ucharcmpoffset); + const int q = *(const unsigned char *) ((const char *) b + stb__ucharcmpoffset); return p < q ? -1 : p > q; } @@ -1599,10 +1600,10 @@ int (*stb_intcmp(int offset))(const void *, const void *) return &stb__intcmp; } -int (*stb_charcmp(int offset))(const void *, const void *) +int (*stb_ucharcmp(int offset))(const void *, const void *) { - stb__charcmpoffset = offset; - return &stb__charcmp; + stb__ucharcmpoffset = offset; + return &stb__ucharcmp; } int (*stb_qsort_strcmp(int offset))(const void *, const void *) @@ -1628,7 +1629,6 @@ int (*stb_doublecmp(int offset))(const void *, const void *) stb__doublecmpoffset = offset; return &stb__doublecmp; } - #endif ////////////////////////////////////////////////////////////////////////////// From 593c9b7192e81970caeefcd4d4868c524e8f0c32 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 02:30:34 -0800 Subject: [PATCH 37/99] rewrite stbi__shiftsigned to use a different, faster algorithm to avoid probelm with clang -O2 to outputting buggy code --- stb_image.h | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/stb_image.h b/stb_image.h index a056138..916d4bb 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4963,21 +4963,27 @@ static int stbi__bitcount(unsigned int a) return a & 0xff; } +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. static int stbi__shiftsigned(int v, int shift, int bits) { - int result; - int z=0; - - if (shift < 0) v <<= -shift; - else v >>= shift; - result = v; - - z = bits; - while (z < 8) { - result += v >> z; - z += bits; - } - return result; + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + assert(v >= 0 && v < 256); + v >>= (8-bits); + assert(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; } typedef struct From b056850ea9118b69325d973f8aef7f843527e299 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 02:52:49 -0800 Subject: [PATCH 38/99] stb_image_write can flip images vertically --- stb_image_write.h | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 9d553e0..94c4cf9 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.07 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.08 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -29,7 +29,7 @@ BUILDING: USAGE: - There are four functions, one for each image file format: + There are five functions, one for each image file format: 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); @@ -37,7 +37,9 @@ USAGE: int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); int stbi_write_jpg(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 + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are expected to open/close your file-equivalent before and after calling these: 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); @@ -151,6 +153,8 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); +extern void stbi_flip_vertically_on_write(int flip_boolean); + #ifdef __cplusplus } #endif @@ -208,6 +212,13 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) +int stbi__flip_vertically_on_write=0; + +void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + typedef struct { stbi_write_func *func; @@ -341,6 +352,9 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i if (y <= 0) return; + if (stbi__flip_vertically_on_write) + vdir *= -1; + if (vdir < 0) j_end = -1, j = y-1; else @@ -412,11 +426,21 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v "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; + int jend, jdir; 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; + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; int len; for (i = 0; i < x; i += len) { @@ -630,7 +654,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f s->func(s->context, buffer, len); for(i=0; i < y; i++) - stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)*x); STBIW_FREE(scratch); return 1; } @@ -932,7 +956,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in for (p=0; p < 2; ++p) { 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; + unsigned char *z = pixels + stride_bytes*(stbi__flip_vertically_on_write ? y-1-j : j); for (i=0; i < n; ++i) switch (type) { case 0: line_buffer[i] = z[i]; break; @@ -954,7 +978,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; } } - if (p) break; + if (p != 0) break; for (i=0; i < x*n; ++i) est += abs((signed char) line_buffer[i]); if (est < bestval) { bestval = est; best = k; } @@ -1318,7 +1342,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in float YDU[64], UDU[64], VDU[64]; for(row = y, pos = 0; row < y+8; ++row) { for(col = x; col < x+8; ++col, ++pos) { - int p = row*width*comp + col*comp; + int p = (stbi__flip_vertically_on_write ? height-1-row : row)*width*comp + col*comp; float r, g, b; if(row >= height) { p -= width*comp*(row+1 - height); @@ -1377,6 +1401,8 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write 1.07 (2017-07-24) doc fix 1.06 (2017-07-23) From 39241e492831b1e05aa1bafacbc937b189896251 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 02:53:14 -0800 Subject: [PATCH 39/99] update version number --- stb_image.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 916d4bb..dbbcb74 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.16 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.17 - 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.17 (2018-01-29) bugfix 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 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 @@ -6975,6 +6976,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug 2.16 (2017-07-23) all functions have 16-bit variants; STBI_NO_STDIO works again; compilation fixes; From 35a3bf41e8f4436c601c4b57030f947fc6a33449 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 02:55:56 -0800 Subject: [PATCH 40/99] Integrate ZLIB changed from Daniel Gibson, fixup credits --- stb_image_write.h | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 85b63d3..79bfc21 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -99,21 +99,16 @@ USAGE: CREDITS: - PNG/BMP/TGA - Sean Barrett - HDR - Baldur Karlsson - TGA monochrome: - Jean-Sebastien Guay - misc enhancements: - Tim Kelsey - TGA RLE - Alan Hickman - initial file IO callback implementation - Emmanuel Julien - JPEG - Jon Olick (original jo_jpeg.cpp code) - Daniel Gibson + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + bugfixes: github:Chribba Guillaume Chereau From 5f1a73fe4e169a65e73657b1c302d43df98ef490 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:18:40 -0800 Subject: [PATCH 41/99] credits, tests --- stb_sprintf.h | 1 + tests/test_c_compilation.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/stb_sprintf.h b/stb_sprintf.h index e8f2b38..a143838 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -13,6 +13,7 @@ // github:trex78 // Jari Komppa (SI suffixes) // Rohit Nirmal +// Marcin Wojdyr // // LICENSE: // diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index 2a54df5..dd31936 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -1,4 +1,15 @@ #include "stb_sprintf.h" +#include "stb_easy_font.h" +#include "stb_herringbone_wang_tile.h" +#include "stb_image.h" +#include "stb_image_write.h" +#include "stb_perlin.h" +#include "stb_dxt.h" +#include "stb_c_lexer.h" +#include "stb_divide.h" +#include "stb_image_resize.h" +#include "stb_rect_pack.h" + #define STB_SPRINTF_IMPLEMENTATION #include "stb_sprintf.h" From da4b342213b62d34d81e510f866cb43845ecdf3a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:23:45 -0800 Subject: [PATCH 42/99] credits --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 0ff3d34..3aa402d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -78,7 +78,7 @@ RECENT REVISION HISTORY: Daniel Gibson (16-bit TGA) socks-the-fox (16-bit PNG) Jeremy Sawicki (handle all ImageNet JPGs) - Optimizations & bugfixes + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) Fabian "ryg" Giesen Arseny Kapoulkine John-Mark Allen From 8cc624142b260c069db2a10f586b30a79dd19f5e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:25:02 -0800 Subject: [PATCH 43/99] credits --- stb_image.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stb_image.h b/stb_image.h index 29a26e6..6dae0e1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -88,16 +88,16 @@ RECENT REVISION HISTORY: 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 - Christian Floisand Kevin Schmidt github:poppolopoppo + the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar + Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex + Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 + Michaelangel007@github Philipp Wiesemann Dale Weiler github:sammyhw + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus + Blazej Dariusz Roszkowski Gregory Mullen github:poppolopoppo + Christian Floisand Kevin Schmidt Baldur Karlsson darealshinji */ #ifndef STBI_INCLUDE_STB_IMAGE_H From 72ef9dcbadd37562cfe75f5ca3e0346954f129f1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:27:58 -0800 Subject: [PATCH 44/99] fix fall-through case warning, add credit --- stb_image.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index 6dae0e1..e0cf014 100644 --- a/stb_image.h +++ b/stb_image.h @@ -97,7 +97,8 @@ RECENT REVISION HISTORY: Michaelangel007@github Philipp Wiesemann Dale Weiler github:sammyhw Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus Blazej Dariusz Roszkowski Gregory Mullen github:poppolopoppo - Christian Floisand Kevin Schmidt Baldur Karlsson darealshinji + Christian Floisand Kevin Schmidt Baldur Karlsson github:darealshinji + Aldo Culquicondor */ #ifndef STBI_INCLUDE_STB_IMAGE_H @@ -5264,13 +5265,13 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req 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; + if (is_rgb16) *is_rgb16 = 0; switch(bits_per_pixel) { case 8: return STBI_grey; case 16: if(is_grey) return STBI_grey_alpha; - // else: fall-through + // fall-through case 15: if(is_rgb16) *is_rgb16 = 1; - return STBI_rgb; + return STBI_rgb; case 24: // fall-through case 32: return bits_per_pixel/8; default: return 0; From 986a5eeeb1a3acdc71d65927177e731436f46c78 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:35:03 -0800 Subject: [PATCH 45/99] fix stb_truetype test file --- tests/stb.dsp | 2 +- tests/test_c_compilation.c | 11 ----------- tests/test_truetype.c | 5 +++-- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/tests/stb.dsp b/tests/stb.dsp index 7e20a14..8e09df5 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 "TT_TEST" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index dd31936..2a54df5 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -1,15 +1,4 @@ #include "stb_sprintf.h" -#include "stb_easy_font.h" -#include "stb_herringbone_wang_tile.h" -#include "stb_image.h" -#include "stb_image_write.h" -#include "stb_perlin.h" -#include "stb_dxt.h" -#include "stb_c_lexer.h" -#include "stb_divide.h" -#include "stb_image_resize.h" -#include "stb_rect_pack.h" - #define STB_SPRINTF_IMPLEMENTATION #include "stb_sprintf.h" diff --git a/tests/test_truetype.c b/tests/test_truetype.c index b432fd4..1ac147b 100644 --- a/tests/test_truetype.c +++ b/tests/test_truetype.c @@ -3,11 +3,12 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#define STB_RECT_PACK_IMPLEMENTATION +#include + +// this isn't meant to compile standalone; link with test_c_compilation.c as well #include "stb_rect_pack.h" #define STB_TRUETYPE_IMPLEMENTATION #include "stb_truetype.h" -#define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" #ifdef TT_TEST From 501e29b2451e514b60b1b7eea2535edbd6e39be7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:36:23 -0800 Subject: [PATCH 46/99] stb_truetype.h docs --- stb_truetype.h | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 51406ab..e5b441e 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -30,33 +30,25 @@ // Imanol Celaya // // Bug/warning reports/fixes: -// "Zer" on mollyrocket -// Cass Everitt -// stoiko (Haemimont Games) -// Brian Hook -// Walter van Niftrik -// David Gow -// David Given -// Ivan-Assen Ivanov -// Anthony Pesch -// Johan Duparc -// Hou Qiming -// Fabian "ryg" Giesen -// Martins Mozeiko -// Cap Petschulat -// Omar Cornut -// github:aloucks -// Peter LaValle -// Sergey Popov -// Giumo X. Clanjor -// Higor Euripedes -// Thomas Fields -// Derek Vinyard -// Cort Stratton -// github:oyvindjam -// +// "Zer" on mollyrocket Fabian "ryg" Giesen +// Cass Everitt Martins Mozeiko +// stoiko (Haemimont Games) Cap Petschulat +// Brian Hook Omar Cornut +// Walter van Niftrik github:aloucks +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Cort Stratton +// github:oyvindjam +// Kenney Phillis Jr. +// +// // VERSION HISTORY // +// 1.18 (2018-01-29) add missing function // 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support // 1.15 (2017-03-03) make more arguments const From 0bd0d049e77ee8f589f8068f62e5391509abc233 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:42:34 -0800 Subject: [PATCH 47/99] stb_image docs --- stb_image.h | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/stb_image.h b/stb_image.h index 9017ed9..9cfcbd6 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.17 (2018-01-29) bugfix + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 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 @@ -79,7 +79,7 @@ RECENT REVISION HISTORY: socks-the-fox (16-bit PNG) Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Mikhail Morozov (1-bit BMP) - Fabian "ryg" Giesen + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) Arseny Kapoulkine John-Mark Allen @@ -418,14 +418,14 @@ STBIDEF void stbi_image_free (void *retval_from_stbi_load); // get image dimensions & components without fully decoding STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); -STBIDEF int stbi_is_16_from_memory(stbi_uc const *buffer, int len); -STBIDEF int stbi_is_16_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); #ifndef STBI_NO_STDIO -STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); -STBIDEF int stbi_is_16 (char const *filename); -STBIDEF int stbi_is_16_from_file (FILE *f); +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); #endif @@ -7038,17 +7038,17 @@ STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) return r; } -STBIDEF int stbi_is_16(char const *filename) +STBIDEF int stbi_is_16_bit(char const *filename) { FILE *f = stbi__fopen(filename, "rb"); int result; if (!f) return stbi__err("can't fopen", "Unable to open file"); - result = stbi_is_16_from_file(f); + result = stbi_is_16_bit_from_file(f); fclose(f); return result; } -STBIDEF int stbi_is_16_from_file(FILE *f) +STBIDEF int stbi_is_16_bit_from_file(FILE *f) { int r; stbi__context s; @@ -7074,14 +7074,14 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int return stbi__info_main(&s,x,y,comp); } -STBIDEF int stbi_is_16_from_memory(stbi_uc const *buffer, int len) +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__is_16_main(&s); } -STBIDEF int stbi_is_16_from_callbacks(stbi_io_callbacks const *c, void *user) +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); @@ -7093,6 +7093,9 @@ STBIDEF int stbi_is_16_from_callbacks(stbi_io_callbacks const *c, void *user) /* revision history: 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings 2.16 (2017-07-23) all functions have 16-bit variants; STBI_NO_STDIO works again; compilation fixes; From f9d78c05a928a7a036da685615fb1f0768e06788 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:49:53 -0800 Subject: [PATCH 48/99] stb_image credits --- stb_image.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stb_image.h b/stb_image.h index 2578204..7bbfac9 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 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 @@ -94,11 +94,11 @@ RECENT REVISION HISTORY: Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 - Michaelangel007@github Philipp Wiesemann Dale Weiler github:sammyhw + Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus - Blazej Dariusz Roszkowski Gregory Mullen github:poppolopoppo - Christian Floisand Kevin Schmidt Baldur Karlsson github:darealshinji - Aldo Culquicondor + Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo + Christian Floisand Kevin Schmidt github:darealshinji + Blazej Dariusz Roszkowski github:Michaelangel007 */ #ifndef STBI_INCLUDE_STB_IMAGE_H From ae00f3a5f0253e553fc03beb7427a2dad6b1fdfa Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:50:42 -0800 Subject: [PATCH 49/99] stb_image credits --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 1ffd829..57488ab 100644 --- a/stb_image.h +++ b/stb_image.h @@ -75,7 +75,7 @@ RECENT REVISION HISTORY: Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) github:urraka (animated gif) Junggon Kim (PNM comments) - github:tocchan (animated gif) Daniel Gibson (16-bit TGA) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) socks-the-fox (16-bit PNG) Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Mikhail Morozov (1-bit BMP) From 4254a9f23798800c912608636ac94acd18cc7bb6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 03:59:48 -0800 Subject: [PATCH 50/99] stb_truetype credits --- stb_truetype.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 07770f8..c0e2858 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -41,9 +41,8 @@ // Anthony Pesch Higor Euripedes // Johan Duparc Thomas Fields // Hou Qiming Derek Vinyard -// Cort Stratton -// github:oyvindjam -// Kenney Phillis Jr. +// Rob Loach Cort Stratton +// Kenney Phillis Jr. github:oyvindjam // // // VERSION HISTORY From 094cb31ec8a84962654a89002825e69dde43b805 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 04:03:18 -0800 Subject: [PATCH 51/99] stb_image: compile as C; stb_image_write: credits --- stb_image.h | 3 ++- stb_image_write.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 57488ab..72fcfc8 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1236,10 +1236,11 @@ STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *u #ifndef STBI_NO_GIF STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { + unsigned char *result; stbi__context s; stbi__start_mem(&s,buffer,len); - unsigned char *result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); if (stbi__vertically_flip_on_load) { stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); } diff --git a/stb_image_write.h b/stb_image_write.h index 60a1396..49f9449 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -132,6 +132,7 @@ CREDITS: Thatcher Ulrich github:poppolopoppo Patrick Boettcher + github:xeekworx LICENSE From ee0ebfc79b8a8abe9cf7a63375c128d06b84c8df Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 04:59:32 -0800 Subject: [PATCH 52/99] version numbers --- README.md | 16 ++++++++-------- stb_sprintf.h | 2 +- stb_truetype.h | 2 +- stb_vorbis.c | 2 +- stretchy_buffer.h | 3 ++- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0bc0844..c53e762 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**[stb_vorbis.c](stb_vorbis.c)** | 1.11 | audio | 5449 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.16 | graphics | 7187 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.17 | graphics | 4566 | parse, decode, and rasterize characters from truetype fonts -**[stb_image_write.h](stb_image_write.h)** | 1.07 | graphics | 1458 | image writing to disk: PNG, TGA, BMP +**[stb_vorbis.c](stb_vorbis.c)** | 1.12 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_image.h](stb_image.h)** | 2.17 | graphics | 7453 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.18 | graphics | 4561 | parse, decode, and rasterize characters from truetype fonts +**[stb_image_write.h](stb_image_write.h)** | 1.08 | graphics | 1555 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.11 | graphics | 624 | simple 2D rectangle packer with decent quality -**[stb_sprintf.h](stb_sprintf.h)** | 1.03 | utility | 1812 | 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_sprintf.h](stb_sprintf.h)** | 1.04 | utility | 1814 | fast sprintf, snprintf for C/C++ +**[stretchy_buffer.h](stretchy_buffer.h)** | 1.03 | utility | 262 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **[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.07 | 3D graphics | 719 | Fabian "ryg" Giesen's real-time DXT compressor @@ -29,11 +29,11 @@ library | lastest version | category | LoC | description **[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.30 | misc | 14328 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**[stb.h](stb.h)** | 2.31 | misc | 14382 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.4 | misc | 186 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 52846 +Total lines of C code: 53278 FAQ diff --git a/stb_sprintf.h b/stb_sprintf.h index 009c634..225eda2 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -1,4 +1,4 @@ -// stb_sprintf - v1.03 - public domain snprintf() implementation +// stb_sprintf - v1.04 - 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 c0e2858..df079ff 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.17 - public domain +// stb_truetype.h - v1.18 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: diff --git a/stb_vorbis.c b/stb_vorbis.c index 49829d2..2c248c2 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.11 - public domain +// Ogg Vorbis audio decoder - v1.12 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. diff --git a/stretchy_buffer.h b/stretchy_buffer.h index bc11083..cbd48a3 100644 --- a/stretchy_buffer.h +++ b/stretchy_buffer.h @@ -1,7 +1,8 @@ -// stretchy_buffer.h - v1.02 - public domain - nothings.org/stb +// stretchy_buffer.h - v1.03 - public domain - nothings.org/stb // a vector<>-like dynamic array for C // // version history: +// 1.03 - compile as C++ maybe // 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 From 76ec599c684b9028887095e5da34384b934718d9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 05:03:38 -0800 Subject: [PATCH 53/99] stb_truetype - remove duplicate definition --- stb_truetype.h | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index df079ff..5967228 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -31,19 +31,19 @@ // // Bug/warning reports/fixes: // "Zer" on mollyrocket Fabian "ryg" Giesen -// Cass Everitt Martins Mozeiko -// stoiko (Haemimont Games) Cap Petschulat -// Brian Hook Omar Cornut -// Walter van Niftrik github:aloucks -// David Gow Peter LaValle -// David Given Sergey Popov -// Ivan-Assen Ivanov Giumo X. Clanjor -// Anthony Pesch Higor Euripedes -// Johan Duparc Thomas Fields -// Hou Qiming Derek Vinyard -// Rob Loach Cort Stratton -// Kenney Phillis Jr. github:oyvindjam -// +// Cass Everitt Martins Mozeiko +// stoiko (Haemimont Games) Cap Petschulat +// Brian Hook Omar Cornut +// Walter van Niftrik github:aloucks +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. github:oyvindjam +// github:vassvik // // VERSION HISTORY // @@ -418,11 +418,6 @@ int main(int arg, char **argv) #define STBTT_fabs(x) fabs(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 From d808adb77f40c83c71a65981b61f1e8ec69fcbcb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 05:17:07 -0800 Subject: [PATCH 54/99] stb_dxt: fix bug with constant color & varying alpha --- stb_dxt.h | 13 +++++++++++-- stb_image.h | 6 ++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index 6504325..541cdc1 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -1,4 +1,4 @@ -// stb_dxt.h - v1.07 - DXT1/DXT5 compressor - public domain +// stb_dxt.h - v1.08 - 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,7 +9,8 @@ // and "high quality" using mode. // // version history: -// v1.07 - bc4; allow not using libc; add STB_DXT_STATIC +// v1.08 - (sbt) fix bug in dxt-with-alpha block +// v1.07 - (stb) bc4; allow not using libc; add STB_DXT_STATIC // 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); @@ -649,6 +650,7 @@ static void stb__InitDXT() void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode) { + unsigned char *data[16][4]; static int init=1; if (init) { stb__InitDXT(); @@ -656,8 +658,15 @@ void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int a } if (alpha) { + int i; stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4); dest += 8; + // make a new copy of the data in which alpha is opaque, + // because code uses a fast test for color constancy + memcpy(data, src, 4*16); + for (i=0; i < 16; ++i) + data[i][3] = 255; + src = &data[0][0]; } stb__CompressColorBlock(dest,(unsigned char*) src,mode); diff --git a/stb_image.h b/stb_image.h index 0e4fde1..0990b0d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,5 +1,5 @@ -/* stb_image - v2.17 - public domain image loader - http://nothings.org/stb_image.h - no warranty implied; use at your own risk +/* stb_image - v2.17 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk Do this: #define STB_IMAGE_IMPLEMENTATION @@ -107,10 +107,8 @@ RECENT REVISION HISTORY: // DOCUMENTATION // // Limitations: -// - no 16-bit-per-channel PNG // - no 12-bit-per-channel JPEG // - no JPEGs with arithmetic coding -// - no 1-bit BMP // - GIF always returns *comp=4 // // Basic usage (see HDR discussion below for HDR usage): From 3f01acced4de5a3983ae590b0bea2de08f4eea3b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 05:39:48 -0800 Subject: [PATCH 55/99] stb_textedit: allow overriding key-input typedef --- stb_textedit.h | 15 +++++++++++---- stb_truetype.h | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 2fb1179..97e87d4 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// stb_textedit.h - v1.11 - public domain - Sean Barrett +// stb_textedit.h - v1.12 - 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 @@ -29,6 +29,7 @@ // // VERSION HISTORY // +// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE // 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 @@ -198,7 +199,7 @@ // void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) // int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) // int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) -// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) +// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) // // Each of these functions potentially updates the string and updates the // state. @@ -232,7 +233,9 @@ // inputs, set a high bit to distinguish the two; then you can define the // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is -// clear. +// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to +// anything other type you wante before including. +// // // When rendering, you can read the cursor position and selection state from // the STB_TexteditState. @@ -711,8 +714,12 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta return 0; } +#ifndef STB_TEXTEDIT_KEYTYPE +#define STB_TEXTEDIT_KEYTYPE int +#endif + // API key: process a keyboard input -static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) +static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) { retry: switch (key) { diff --git a/stb_truetype.h b/stb_truetype.h index 5967228..5eface5 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -162,7 +162,7 @@ // measurement for describing font size, defined as 72 points per inch. // stb_truetype provides a point API for compatibility. However, true // "per inch" conventions don't make much sense on computer displays -// since they different monitors have different number of pixels per +// since different monitors have different number of pixels per // inch. For example, Windows traditionally uses a convention that // there are 96 pixels per inch, thus making 'inch' measurements have // nothing to do with inches, and thus effectively defining a point to @@ -172,6 +172,39 @@ // for non-commercial fonts, thus making fonts scaled in points // according to the TrueType spec incoherently sized in practice. // +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to Date: Mon, 29 Jan 2018 06:06:29 -0800 Subject: [PATCH 56/99] stb_image_write: fix for fopen_s failure case --- stb_image_write.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 49f9449..d318e0e 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -273,7 +273,8 @@ static int stbi__start_write_file(stbi__write_context *s, const char *filename) { FILE *f; #ifdef STBI_MSC_SECURE_CRT - fopen_s(&f, filename, "wb"); + if (fopen_s(&f, filename, "wb")) + f = NULL; #else f = fopen(filename, "wb"); #endif @@ -1102,7 +1103,8 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (png == NULL) return 0; #ifdef STBI_MSC_SECURE_CRT - fopen_s(&f, filename, "wb"); + if (fopen_s(&f, filename, "wb")) + f = NULL; #else f = fopen(filename, "wb"); #endif From 3025377f4a465055e8359dc0513151331edff7c1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 07:23:54 -0800 Subject: [PATCH 57/99] fix stb_textedit redo, from omar cornut --- stb_textedit.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 97e87d4..91a52da 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -29,7 +29,7 @@ // // VERSION HISTORY // -// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE +// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash // 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 @@ -1119,15 +1119,18 @@ static void stb_textedit_discard_redo(StbUndoState *state) // if the k'th undo state has characters, clean those up if (state->undo_rec[k].char_storage >= 0) { int n = state->undo_rec[k].insert_length, i; - // delete n characters from all other records + // move the remaining redo character data to the end of the buffer state->redo_char_point = state->redo_char_point + (short) n; // vsnet05 - STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); + STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); + // adjust the position of all the other records to account for above memmove for (i=state->redo_point; i < k; ++i) if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05 + state->undo_rec[i].char_storage += (short) n; // vsnet05 } + // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' + STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); + // now move redo_point to point to the new one ++state->redo_point; - STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); } } @@ -1210,11 +1213,11 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) // there's definitely room to store the characters eventually while (s->undo_char_point + u.delete_length > s->redo_char_point) { - // there's currently not enough room, so discard a redo record - stb_textedit_discard_redo(s); // should never happen: if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) return; + // there's currently not enough room, so discard a redo record + stb_textedit_discard_redo(s); } r = &s->undo_rec[s->redo_point-1]; @@ -1285,6 +1288,7 @@ static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) if (r.insert_length) { // easy case: need to insert n characters STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); + s->redo_char_point += r.insert_length; } state->cursor = r.where + r.insert_length; From db4d92891c78cdf32753b022b7081dd9a32d8aa6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 07:44:04 -0800 Subject: [PATCH 58/99] fix stb_sdict_for() --- stb.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/stb.h b/stb.h index c6a39f3..5a4e0de 100644 --- a/stb.h +++ b/stb.h @@ -4246,12 +4246,22 @@ STB_EXTERN void stb_sdict_delete(stb_sdict *); STB_EXTERN void * stb_sdict_change(stb_sdict *, char *str, void *p); STB_EXTERN int stb_sdict_count(stb_sdict *d); +STB_EXTERN int stb_sdict_internal_limit(stb_sdict *d); +STB_EXTERN char * stb_sdict_internal_key(stb_sdict *d, int n); +STB_EXTERN void * stb_sdict_internal_value(stb_sdict *d, int n); + #define stb_sdict_for(d,i,q,z) \ - for(i=0; i < (d)->limit ? q=(d)->table[i].k,z=(d)->table[i].v,1 : 0; ++i) \ + for(i=0; i < stb_sdict_internal_limit(d) ? (q=stb_sdict_internal_key(d,i),z=stb_sdict_internal_value(d,i),1) : 0; ++i) \ if (q==NULL||q==(void *) 1);else // reversed makes macro friendly #ifdef STB_DEFINE +// if in same translation unit, for speed, don't call accessors +#undef stb_sdict_for +#define stb_sdict_for(d,i,q,z) \ + for(i=0; i < (d)->limit ? (q=(d)->table[i].k,z=(d)->table[i].v,1) : 0; ++i) \ + if (q==NULL||q==(void *) 1);else // reversed makes macro friendly + #define STB_DEL ((void *) 1) #define STB_SDEL ((char *) 1) @@ -4271,6 +4281,19 @@ int stb_sdict_count(stb_sdict *a) return a->count; } +int stb_sdict_internal_limit(stb_sdict *a) +{ + return a->limit; +} +char* stb_sdict_internal_key(stb_sdict *a, int n) +{ + return a->table[n].k; +} +void* stb_sdict_internal_value(stb_sdict *a, int n) +{ + return a->table[n].v; +} + stb_sdict * stb_sdict_new(int use_arena) { stb_sdict *d = stb_sdict_create(); From 87352fdcb55489b0e143e035942222dcf058e6c0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 07:44:54 -0800 Subject: [PATCH 59/99] stb_truetype: fix bug in handling of stbtt_hheap that could cause severe badness --- stb_truetype.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 5eface5..98c8acc 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -43,7 +43,7 @@ // Hou Qiming Derek Vinyard // Rob Loach Cort Stratton // Kenney Phillis Jr. github:oyvindjam -// github:vassvik +// Brian Costabile github:vassvik // // VERSION HISTORY // @@ -2412,7 +2412,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; } } From 9b2522c3d53b16cefa99af660e1d0079cbaf4a9e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 07:48:12 -0800 Subject: [PATCH 60/99] stbi_is_hdr_from_file needs to reset file position --- stb_image.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 0990b0d..14c2f7e 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1333,9 +1333,12 @@ STBIDEF int stbi_is_hdr (char const *filename) STBIDEF int stbi_is_hdr_from_file(FILE *f) { #ifndef STBI_NO_HDR + long pos = ftell(f), res; stbi__context s; stbi__start_file(&s,f); - return stbi__hdr_test(&s); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; #else STBI_NOTUSED(f); return 0; From 74a21dc6158b7688bac8e1f375eef519b6401708 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 07:52:21 -0800 Subject: [PATCH 61/99] fix compiler warnings --- stb_image.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 14c2f7e..952ec49 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1750,7 +1750,8 @@ typedef struct static int stbi__build_huffman(stbi__huffman *h, int *count) { - int i,j,k=0,code; + int i,j,k=0; + unsigned int code; // build size list for each symbol (from JPEG spec) for (i=0; i < 16; ++i) for (j=0; j < count[i]; ++j) @@ -2157,7 +2158,7 @@ stbi_inline static stbi_uc stbi__clamp(int x) } #define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) -#define stbi__fsh(x) ((x) << 12) +#define stbi__fsh(x) ((x) * 4096) // derived from jidctint -- DCT_ISLOW #define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ @@ -4720,7 +4721,7 @@ static void stbi__de_iphone(stbi__png *z) } } -#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { From 4fd9019c0fd9088d1e288649372babc8e3ab6e16 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 07:57:23 -0800 Subject: [PATCH 62/99] stb_image: avoid signed left shifts --- stb_image.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 952ec49..2656def 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1767,7 +1767,7 @@ static int stbi__build_huffman(stbi__huffman *h, int *count) if (h->size[k] == j) { while (h->size[k] == j) h->code[k++] = (stbi__uint16) (code++); - if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); } // compute largest code + 1 for this size, preshifted as needed later h->maxcode[j] = code << (16-j); @@ -1811,7 +1811,7 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) 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)); + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); } } } @@ -1820,7 +1820,7 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) static void stbi__grow_buffer_unsafe(stbi__jpeg *j) { do { - int b = j->nomore ? 0 : stbi__get8(j->s); + unsigned 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); // consume fill bytes From 445473bdb5f7813487b6f8f808d3ae84801937da Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 08:03:56 -0800 Subject: [PATCH 63/99] stb_image_write: handle malloc failure in zlib --- stb_image_write.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb_image_write.h b/stb_image_write.h index d318e0e..eaf5093 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -817,6 +817,8 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l int i,j, bitcount=0; unsigned char *out = NULL; unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (hash_table == NULL) + return NULL; if (quality < 5) quality = 5; stbiw__sbpush(out, 0x78); // DEFLATE 32K window From b2c2419b1bf03ec350b07fd2f122e7768252a30e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 08:14:53 -0800 Subject: [PATCH 64/99] stb_image: avoid arithmetic overflow in png case --- stb_image.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb_image.h b/stb_image.h index 2656def..ed456fd 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4341,8 +4341,10 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r 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"); + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_len = (img_width_bytes + 1) * y; + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), // so just check for raw_len < img_len always. From 037926ab74b0d420a1f760b6377aae7656b6dca5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 08:18:19 -0800 Subject: [PATCH 65/99] fix warnings, bad error handling --- stb_image.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index ed456fd..5f60fea 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3139,8 +3139,8 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) } 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"); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); } else { if (!stbi__process_marker(j, m)) return 0; } @@ -5324,10 +5324,10 @@ static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) switch(bits_per_pixel) { case 8: return STBI_grey; case 16: if(is_grey) return STBI_grey_alpha; - // fall-through + // fallthrough case 15: if(is_rgb16) *is_rgb16 = 1; return STBI_rgb; - case 24: // fall-through + case 24: // fallthrough case 32: return bits_per_pixel/8; default: return 0; } From 476b4c7a72ef2c9e2b0f36a95171c735bdcba0cf Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 08:22:21 -0800 Subject: [PATCH 66/99] update readme --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c53e762..259f71b 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,16 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.12 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.17 | graphics | 7453 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.18 | graphics | 4561 | parse, decode, and rasterize characters from truetype fonts -**[stb_image_write.h](stb_image_write.h)** | 1.08 | graphics | 1555 | image writing to disk: PNG, TGA, BMP +**[stb_image.h](stb_image.h)** | 2.17 | graphics | 7457 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.18 | graphics | 4589 | parse, decode, and rasterize characters from truetype fonts +**[stb_image_write.h](stb_image_write.h)** | 1.08 | graphics | 1559 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.11 | graphics | 624 | simple 2D rectangle packer with decent quality **[stb_sprintf.h](stb_sprintf.h)** | 1.04 | utility | 1814 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.03 | utility | 262 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ -**[stb_textedit.h](stb_textedit.h)** | 1.11 | user interface | 1393 | guts of a text editor for games etc implementing them from scratch +**[stb_textedit.h](stb_textedit.h)** | 1.12 | user interface | 1404 | 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.07 | 3D graphics | 719 | Fabian "ryg" Giesen's real-time DXT compressor +**[stb_dxt.h](stb_dxt.h)** | 1.08 | 3D graphics | 728 | 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 @@ -29,11 +29,11 @@ library | lastest version | category | LoC | description **[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.31 | misc | 14382 | helper functions for C, mostly redundant in C++; basically author's personal stuff +**[stb.h](stb.h)** | 2.31 | misc | 14405 | helper functions for C, mostly redundant in C++; basically author's personal stuff **[stb_leakcheck.h](stb_leakcheck.h)** | 0.4 | misc | 186 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 53278 +Total lines of C code: 53357 FAQ From dfff6f5e7cd412876fe6282f157c1928b99d1de9 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 13:15:10 -0800 Subject: [PATCH 67/99] stb_image: fix assert macro usage; stb_vorbis: changelog --- stb_image.h | 6 +++--- stb_vorbis.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index 5f60fea..50286af 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.17 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.17b - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: @@ -5041,9 +5041,9 @@ static int stbi__shiftsigned(int v, int shift, int bits) v <<= -shift; else v >>= shift; - assert(v >= 0 && v < 256); + STBI_ASSERT(v >= 0 && v < 256); v >>= (8-bits); - assert(bits >= 0 && bits <= 8); + STBI_ASSERT(bits >= 0 && bits <= 8); return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; } diff --git a/stb_vorbis.c b/stb_vorbis.c index 2c248c2..730768c 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.12 - public domain +// Ogg Vorbis audio decoder - v1.13 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -32,6 +32,7 @@ // manxorist@github saga musix github:infatum // // Partial history: +// 1.13 - 2018/01/29 - fix truncation of last frame (hopefully) // 1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files // 1.11 - 2017/07/23 - fix MinGW compilation // 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory From 7855d2dc8719d91da0ef7aa3d8053c35931d1d81 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 14:52:14 -0800 Subject: [PATCH 68/99] version numbers in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 259f71b..36fdebd 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**[stb_vorbis.c](stb_vorbis.c)** | 1.12 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.17 | graphics | 7457 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_vorbis.c](stb_vorbis.c)** | 1.13 | audio | 5463 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_image.h](stb_image.h)** | 2.17b | graphics | 7457 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.18 | graphics | 4589 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.08 | graphics | 1559 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.4 | misc | 186 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 53357 +Total lines of C code: 53358 FAQ From 663deb3a43219c764c87a3591a55f5163c06230a Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 15:20:54 -0800 Subject: [PATCH 69/99] redo lost stb_vorbis fixes --- stb_vorbis.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 730768c..c7d4b84 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.13 - public domain +// Ogg Vorbis audio decoder - v1.13b - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -3398,7 +3398,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, 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); + uint32 current_end = f->known_loc_for_packet; // then let's infer the size of the (probably) short final frame if (current_end < f->current_loc + (right_end-left_start)) { if (current_end < f->current_loc) { @@ -3407,7 +3407,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, } else { *len = current_end - f->current_loc; } - *len += left_start; + *len += left_start; // this doesn't seem right, but has no ill effect on my test files if (*len > right_end) *len = right_end; // this should never happen f->current_loc += *len; return TRUE; From f2974f6c1c579abd7f54f4a3271effb18c3996a8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 29 Jan 2018 15:21:12 -0800 Subject: [PATCH 70/99] update readme version number --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36fdebd..bb5a4f2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- -**[stb_vorbis.c](stb_vorbis.c)** | 1.13 | audio | 5463 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_vorbis.c](stb_vorbis.c)** | 1.13b | audio | 5463 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_image.h](stb_image.h)** | 2.17b | graphics | 7457 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.18 | graphics | 4589 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.08 | graphics | 1559 | image writing to disk: PNG, TGA, BMP From e460d1a8d8cce54eadcf585241d8c12fd14cd59c Mon Sep 17 00:00:00 2001 From: Daniel Ribeiro Maciel Date: Thu, 24 Aug 2017 15:22:52 -0300 Subject: [PATCH 71/99] Add basic GPOS kerning --- stb_truetype.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 238 insertions(+), 3 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 98c8acc..2073be9 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -22,6 +22,7 @@ // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering // Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning // // Misc other: // Ryan Gordon @@ -695,7 +696,7 @@ struct stbtt_fontinfo int numGlyphs; // number of glyphs, needed for range checking - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf + int loca,head,glyf,hhea,hmtx,kern,gpos; // 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 @@ -1338,6 +1339,7 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; @@ -2256,7 +2258,7 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -2286,9 +2288,242 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, return 0; } +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch(coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + m = (l + r) >> 1; + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + } break; + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + m = (l + r) >> 1; + stbtt_uint8 *rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + } break; + + default: { + // There are no other cases. + STBTT_assert(false); + } break; + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch(classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + + classDefTable = classDef1ValueArray + 2 * glyphCount; + } break; + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + m = (l + r) >> 1; + stbtt_uint8 *classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + + classDefTable = classRangeRecords + 6 * classRangeCount; + } break; + + default: { + // There are no other cases. + STBTT_assert(false); + } break; + } + + return -1; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + if (!info->gpos) return 0; + + stbtt_uint8 *data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + stbtt_uint16 lookupListOffset = ttUSHORT(data+8); + stbtt_uint8 *lookupList = data + lookupListOffset; + + stbtt_uint16 lookupCount = ttUSHORT(lookupList); + for (stbtt_int32 i=0; i> 1; + stbtt_uint8 *pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + stbtt_uint16 secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } break; + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + STBTT_assert(glyph1class < class1Count); + STBTT_assert(glyph2class < class2Count); + + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { + stbtt_uint8 *class1Records = table + 16; + stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); + stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } + } break; + + default: { + // There are no other cases. + STBTT_assert(false); + } break; + } + } + } break; + + default: { + // TODO: Implement other stuff. + } break; + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + + if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } From 06fedddb4d8610383a1d1df9a6bcfac92dc85a94 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 02:56:16 -0800 Subject: [PATCH 72/99] fix stb_dxt.h; fix misspelled STB_DXT_IMPLEMENTATION in test jig --- stb_dxt.h | 20 ++++++++++---------- tests/test_c_compilation.c | 5 +++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index 541cdc1..2fa84fa 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -1,4 +1,4 @@ -// stb_dxt.h - v1.08 - DXT1/DXT5 compressor - public domain +// stb_dxt.h - v1.08b - 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 // @@ -32,11 +32,6 @@ #ifndef STB_INCLUDE_STB_DXT_H #define STB_INCLUDE_STB_DXT_H -// compression mode (bitflags) -#define STB_DXT_NORMAL 0 -#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 @@ -47,15 +42,21 @@ extern "C" { #define STBDDEF extern #endif +// compression mode (bitflags) +#define STB_DXT_NORMAL 0 +#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. + STBDDEF void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); STBDDEF void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src_r_one_byte_per_pixel); STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel); +#define STB_COMPRESS_DXT_BLOCK + #ifdef __cplusplus } #endif - -#define STB_COMPRESS_DXT_BLOCK +#endif // STB_INCLUDE_STB_DXT_H #ifdef STB_DXT_IMPLEMENTATION @@ -650,7 +651,7 @@ static void stb__InitDXT() void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode) { - unsigned char *data[16][4]; + unsigned char data[16][4]; static int init=1; if (init) { stb__InitDXT(); @@ -683,7 +684,6 @@ void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src) stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2); } #endif // STB_DXT_IMPLEMENTATION -#endif // STB_INCLUDE_STB_DXT_H /* ------------------------------------------------------------------------------ diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index 2a54df5..3dd6c16 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -4,7 +4,6 @@ #define STB_PERLIN_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION -#define STB_DXT_IMPLEMENATION #define STB_C_LEXER_IMPLEMENTATIOn #define STB_DIVIDE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION @@ -19,12 +18,14 @@ #include "stb_image.h" #include "stb_image_write.h" #include "stb_perlin.h" -#include "stb_dxt.h" #include "stb_c_lexer.h" #include "stb_divide.h" #include "stb_image_resize.h" #include "stb_rect_pack.h" +#define STB_DXT_IMPLEMENTATION +#include "stb_dxt.h" + #define STBVOX_CONFIG_MODE 1 #include "stb_voxel_render.h" From 3ac351f39dd7b5d46a6047705e48d57ed4ba3583 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:16:47 -0800 Subject: [PATCH 73/99] break out stb_lib.h --- tests/prerelease/stb_lib.h | 3305 +++++++++++++++++++++++++++++++++ tests/stb.dsw | 12 + tests/stblib.dsp | 102 + tests/stblib_test.c | 11 + tests/stblib_test_companion.c | 4 + 5 files changed, 3434 insertions(+) create mode 100644 tests/prerelease/stb_lib.h create mode 100644 tests/stblib.dsp create mode 100644 tests/stblib_test.c create mode 100644 tests/stblib_test_companion.c diff --git a/tests/prerelease/stb_lib.h b/tests/prerelease/stb_lib.h new file mode 100644 index 0000000..f4445c6 --- /dev/null +++ b/tests/prerelease/stb_lib.h @@ -0,0 +1,3305 @@ +/* stb_lib.h - v1.00 - http://nothings.org/stb + no warranty is offered or implied; use this code at your own risk + + ============================================================================ + You MUST + + #define STB_LIB_IMPLEMENTATION + + in EXACTLY _one_ C or C++ file that includes this header, BEFORE the + include, like this: + + #define STB_LIB_IMPLEMENTATION + #include "stblib_files.h" + + All other files should just #include "stblib_files.h" without the #define. + ============================================================================ + +LICENSE + + See end of file for license information. + +CREDITS + + Written by Sean Barrett. + + Fixes: + Philipp Wiesemann Robert Nix + r-lyeh blackpawn + github:Mojofreem Ryan Whitworth + Vincent Isambart Mike Sartain + Eugene Opalev Tim Sjostrand + github:infatum Dave Butler +*/ + +#ifndef STB_INCLUDE_STB_LIB_H + +#include + +#if defined(_WIN32) && !defined(__MINGW32__) + #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 +#endif + +#include // stdlib could have min/max +#include // need FILE +#include // stb_define_hash needs memcpy/memset +#include // stb_dirtree + +typedef unsigned char stb_uchar; +typedef unsigned char stb_uint8; +typedef unsigned int stb_uint; +typedef unsigned short stb_uint16; +typedef short stb_int16; +typedef signed char stb_int8; +#if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32) + typedef unsigned long stb_uint32; + typedef long stb_int32; +#else + typedef unsigned int stb_uint32; + typedef int stb_int32; +#endif +typedef char stb__testsize2_16[sizeof(stb_uint16)==2 ? 1 : -1]; +typedef char stb__testsize2_32[sizeof(stb_uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER + typedef unsigned __int64 stb_uint64; + typedef __int64 stb_int64; + #define STB_IMM_UINT64(literalui64) (literalui64##ui64) +#else + // ?? + typedef unsigned long long stb_uint64; + typedef long long stb_int64; + #define STB_IMM_UINT64(literalui64) (literalui64##ULL) +#endif +typedef char stb__testsize2_64[sizeof(stb_uint64)==8 ? 1 : -1]; + +#ifdef __cplusplus + #define STB_EXTERN extern "C" +#else + #define STB_EXTERN extern +#endif + +// check for well-known debug defines +#if defined(DEBUG) || defined(_DEBUG) || defined(DBG) + #ifndef NDEBUG + #define STB_DEBUG + #endif +#endif + +#ifdef STB_DEBUG + #include +#endif +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION + #include + #include + #include + #include + #include + #ifndef _WIN32 + #include + #else + #include // _mktemp + #include // _rmdir + #endif + #include // stat()/_stat() + #include // stat()/_stat() +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Miscellany +// + +#ifdef _WIN32 + #define stb_stricmp(a,b) stricmp(a,b) + #define stb_strnicmp(a,b,n) strnicmp(a,b,n) +#else + #define stb_stricmp(a,b) strcasecmp(a,b) + #define stb_strnicmp(a,b,n) strncasecmp(a,b,n) +#endif + +#ifndef STB_INCLUDE_STB_LIB_H +STB_EXTERN void stb_fatal(char *fmt, ...); +STB_EXTERN void stb_swap(void *p, void *q, size_t sz); +STB_EXTERN double stb_linear_remap(double x, double x_min, double x_max, + double out_min, double out_max); + +#define stb_arrcount(x) (sizeof(x)/sizeof((x)[0])) +#define stb_lerp(t,a,b) ( (a) + (t) * (float) ((b)-(a)) ) +#define stb_unlerp(t,a,b) ( ((t) - (a)) / (float) ((b) - (a)) ) + +#endif + + +#ifdef STB_LIB_IMPLEMENTATION +void stb_fatal(char *s, ...) +{ + va_list a; + va_start(a,s); + fputs("Fatal error: ", stderr); + vfprintf(stderr, s, a); + va_end(a); + fputs("\n", stderr); + #ifdef STB_DEBUG + #ifdef _MSC_VER + #ifndef _WIN64 + __asm int 3; // trap to debugger! + #else + __debugbreak(); + #endif + #else + __builtin_trap(); + #endif + #endif + exit(1); +} + +typedef struct { char d[4]; } stb__4; +typedef struct { char d[8]; } stb__8; + +// optimize the small cases, though you shouldn't be calling this for those! +void stb_swap(void *p, void *q, size_t sz) +{ + char buffer[256]; + if (p == q) return; + if (sz == 4) { + stb__4 temp = * ( stb__4 *) p; + * (stb__4 *) p = * ( stb__4 *) q; + * (stb__4 *) q = temp; + return; + } else if (sz == 8) { + stb__8 temp = * ( stb__8 *) p; + * (stb__8 *) p = * ( stb__8 *) q; + * (stb__8 *) q = temp; + return; + } + + while (sz > sizeof(buffer)) { + stb_swap(p, q, sizeof(buffer)); + p = (char *) p + sizeof(buffer); + q = (char *) q + sizeof(buffer); + sz -= sizeof(buffer); + } + + memcpy(buffer, p , sz); + memcpy(p , q , sz); + memcpy(q , buffer, sz); +} + +#ifdef stb_linear_remap +#undef stb_linear_remap +#endif + +double stb_linear_remap(double x, double x_min, double x_max, + double out_min, double out_max) +{ + return stb_lerp(stb_unlerp(x,x_min,x_max),out_min,out_max); +} + +#define stb_linear_remap(t,a,b,c,d) stb_lerp(stb_unlerp(t,a,b),c,d) +#endif // STB_LIB_IMPLEMENTATION + +#ifndef STB_INCLUDE_STB_LIB_H +// avoid unnecessary function call, but define function so its address can be taken +#ifndef stb_linear_remap +#define stb_linear_remap(t,a,b,c,d) stb_lerp(stb_unlerp(t,a,b),c,d) +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// cross-platform snprintf because they keep changing that, +// and with old compilers without vararg macros we can't write +// a macro wrapper to fix it up + +#ifndef STB_INCLUDE_STB_LIB_H +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); +STB_EXTERN char *stb_sprintf(const char *fmt, ...); +#endif + +#ifdef STB_LIB_IMPLEMENTATION + +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 >= (int) 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); + stb_vsnprintf(buffer,1024,fmt,v); + va_end(v); + return buffer; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Windows UTF8 filename handling +// +// Windows stupidly treats 8-bit filenames as some dopey code page, +// rather than utf-8. If we want to use utf8 filenames, we have to +// convert them to WCHAR explicitly and call WCHAR versions of the +// file functions. So, ok, we do. + + +#ifndef STB_INCLUDE_STB_LIB_H +#ifdef _WIN32 + #define stb__fopen(x,y) _wfopen((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y)) + #define stb__windows(x,y) x +#else + #define stb__fopen(x,y) fopen(x,y) + #define stb__windows(x,y) y +#endif + + +typedef unsigned short stb__wchar; + +STB_EXTERN stb__wchar * stb_from_utf8(stb__wchar *buffer, char *str, int n); +STB_EXTERN char * stb_to_utf8 (char *buffer, stb__wchar *str, int n); + +STB_EXTERN stb__wchar *stb__from_utf8(char *str); +STB_EXTERN stb__wchar *stb__from_utf8_alt(char *str); +STB_EXTERN char *stb__to_utf8(stb__wchar *str); +#endif + +#ifdef STB_LIB_IMPLEMENTATION +stb__wchar * stb_from_utf8(stb__wchar *buffer, char *ostr, int n) +{ + unsigned char *str = (unsigned char *) ostr; + stb_uint32 c; + int i=0; + --n; + while (*str) { + if (i >= n) + return NULL; + if (!(*str & 0x80)) + buffer[i++] = *str++; + else if ((*str & 0xe0) == 0xc0) { + if (*str < 0xc2) return NULL; + c = (*str++ & 0x1f) << 6; + if ((*str & 0xc0) != 0x80) return NULL; + buffer[i++] = c + (*str++ & 0x3f); + } else if ((*str & 0xf0) == 0xe0) { + if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return NULL; + if (*str == 0xed && str[1] > 0x9f) return NULL; // str[1] < 0x80 is checked below + c = (*str++ & 0x0f) << 12; + if ((*str & 0xc0) != 0x80) return NULL; + c += (*str++ & 0x3f) << 6; + if ((*str & 0xc0) != 0x80) return NULL; + buffer[i++] = c + (*str++ & 0x3f); + } else if ((*str & 0xf8) == 0xf0) { + if (*str > 0xf4) return NULL; + if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return NULL; + if (*str == 0xf4 && str[1] > 0x8f) return NULL; // str[1] < 0x80 is checked below + c = (*str++ & 0x07) << 18; + if ((*str & 0xc0) != 0x80) return NULL; + c += (*str++ & 0x3f) << 12; + if ((*str & 0xc0) != 0x80) return NULL; + c += (*str++ & 0x3f) << 6; + if ((*str & 0xc0) != 0x80) return NULL; + c += (*str++ & 0x3f); + // utf-8 encodings of values used in surrogate pairs are invalid + if ((c & 0xFFFFF800) == 0xD800) return NULL; + if (c >= 0x10000) { + c -= 0x10000; + if (i + 2 > n) return NULL; + buffer[i++] = 0xD800 | (0x3ff & (c >> 10)); + buffer[i++] = 0xDC00 | (0x3ff & (c )); + } + } else + return NULL; + } + buffer[i] = 0; + return buffer; +} + +char * stb_to_utf8(char *buffer, stb__wchar *str, int n) +{ + int i=0; + --n; + while (*str) { + if (*str < 0x80) { + if (i+1 > n) return NULL; + buffer[i++] = (char) *str++; + } else if (*str < 0x800) { + if (i+2 > n) return NULL; + buffer[i++] = 0xc0 + (*str >> 6); + buffer[i++] = 0x80 + (*str & 0x3f); + str += 1; + } else if (*str >= 0xd800 && *str < 0xdc00) { + stb_uint32 c; + if (i+4 > n) return NULL; + c = ((str[0] - 0xd800) << 10) + ((str[1]) - 0xdc00) + 0x10000; + buffer[i++] = 0xf0 + (c >> 18); + buffer[i++] = 0x80 + ((c >> 12) & 0x3f); + buffer[i++] = 0x80 + ((c >> 6) & 0x3f); + buffer[i++] = 0x80 + ((c ) & 0x3f); + str += 2; + } else if (*str >= 0xdc00 && *str < 0xe000) { + return NULL; + } else { + if (i+3 > n) return NULL; + buffer[i++] = 0xe0 + (*str >> 12); + buffer[i++] = 0x80 + ((*str >> 6) & 0x3f); + buffer[i++] = 0x80 + ((*str ) & 0x3f); + str += 1; + } + } + buffer[i] = 0; + return buffer; +} + +stb__wchar *stb__from_utf8(char *str) +{ + static stb__wchar buffer[4096]; + return stb_from_utf8(buffer, str, 4096); +} + +stb__wchar *stb__from_utf8_alt(char *str) +{ + static stb__wchar buffer[4096]; + return stb_from_utf8(buffer, str, 4096); +} + +char *stb__to_utf8(stb__wchar *str) +{ + static char buffer[4096]; + return stb_to_utf8(buffer, str, 4096); +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// qsort Compare Routines +// NOT THREAD SAFE + +#ifndef STB_INCLUDE_STB_LIB_H +STB_EXTERN int (*stb_intcmp(int offset))(const void *a, const void *b); +STB_EXTERN int (*stb_qsort_strcmp(int offset))(const void *a, const void *b); +STB_EXTERN int (*stb_qsort_stricmp(int offset))(const void *a, const void *b); +STB_EXTERN int (*stb_floatcmp(int offset))(const void *a, const void *b); +STB_EXTERN int (*stb_doublecmp(int offset))(const void *a, const void *b); +STB_EXTERN int (*stb_ucharcmp(int offset))(const void *a, const void *b); +STB_EXTERN int (*stb_charcmp(int offset))(const void *a, const void *b); +#endif + +#ifdef STB_LIB_IMPLEMENTATION +static int stb__intcmpoffset, stb__ucharcmpoffset, stb__strcmpoffset; +static int stb__floatcmpoffset, stb__doublecmpoffset, stb__charcmpoffset; + +int stb__intcmp(const void *a, const void *b) +{ + const int p = *(const int *) ((const char *) a + stb__intcmpoffset); + const int q = *(const int *) ((const char *) b + stb__intcmpoffset); + return p < q ? -1 : p > q; +} + +int stb__ucharcmp(const void *a, const void *b) +{ + const int p = *(const unsigned char *) ((const char *) a + stb__ucharcmpoffset); + const int q = *(const unsigned char *) ((const char *) b + stb__ucharcmpoffset); + return p < q ? -1 : p > q; +} + +int stb__charcmp(const void *a, const void *b) +{ + const int p = *(const char *) ((const char *) a + stb__ucharcmpoffset); + const int q = *(const char *) ((const char *) b + stb__ucharcmpoffset); + return p < q ? -1 : p > q; +} + +int stb__floatcmp(const void *a, const void *b) +{ + const float p = *(const float *) ((const char *) a + stb__floatcmpoffset); + const float q = *(const float *) ((const char *) b + stb__floatcmpoffset); + return p < q ? -1 : p > q; +} + +int stb__doublecmp(const void *a, const void *b) +{ + const double p = *(const double *) ((const char *) a + stb__doublecmpoffset); + const double q = *(const double *) ((const char *) b + stb__doublecmpoffset); + return p < q ? -1 : p > q; +} + +int stb__qsort_strcmp(const void *a, const void *b) +{ + const char *p = *(const char **) ((const char *) a + stb__strcmpoffset); + const char *q = *(const char **) ((const char *) b + stb__strcmpoffset); + return strcmp(p,q); +} + +int stb__qsort_stricmp(const void *a, const void *b) +{ + const char *p = *(const char **) ((const char *) a + stb__strcmpoffset); + const char *q = *(const char **) ((const char *) b + stb__strcmpoffset); + return stb_stricmp(p,q); +} + +int (*stb_intcmp(int offset))(const void *, const void *) +{ + stb__intcmpoffset = offset; + return &stb__intcmp; +} + +int (*stb_ucharcmp(int offset))(const void *, const void *) +{ + stb__ucharcmpoffset = offset; + return &stb__ucharcmp; +} + +int (*stb_charcmp(int offset))(const void *, const void *) +{ + stb__charcmpoffset = offset; + return &stb__ucharcmp; +} + +int (*stb_qsort_strcmp(int offset))(const void *, const void *) +{ + stb__strcmpoffset = offset; + return &stb__qsort_strcmp; +} + +int (*stb_qsort_stricmp(int offset))(const void *, const void *) +{ + stb__strcmpoffset = offset; + return &stb__qsort_stricmp; +} + +int (*stb_floatcmp(int offset))(const void *, const void *) +{ + stb__floatcmpoffset = offset; + return &stb__floatcmp; +} + +int (*stb_doublecmp(int offset))(const void *, const void *) +{ + stb__doublecmpoffset = offset; + return &stb__doublecmp; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// String Processing +// + +#ifndef STB_INCLUDE_STB_LIB_H +#define stb_prefixi(s,t) (0==stb_strnicmp((s),(t),strlen(t))) + +enum stb_splitpath_flag +{ + STB_PATH = 1, + STB_FILE = 2, + STB_EXT = 4, + STB_PATH_FILE = STB_PATH + STB_FILE, + STB_FILE_EXT = STB_FILE + STB_EXT, + STB_EXT_NO_PERIOD = 8, +}; + +STB_EXTERN char * stb_skipwhite(char *s); +STB_EXTERN char * stb_trimwhite(char *s); +STB_EXTERN char * stb_skipnewline(char *s); +STB_EXTERN char * stb_strncpy(char *s, char *t, int n); +STB_EXTERN char * stb_substr(char *t, int n); +STB_EXTERN char * stb_duplower(char *s); +STB_EXTERN void stb_tolower (char *s); +STB_EXTERN char * stb_strchr2 (char *s, char p1, char p2); +STB_EXTERN char * stb_strrchr2(char *s, char p1, char p2); +STB_EXTERN char * stb_strtok(char *output, char *src, char *delimit); +STB_EXTERN char * stb_strtok_keep(char *output, char *src, char *delimit); +STB_EXTERN char * stb_strtok_invert(char *output, char *src, char *allowed); +STB_EXTERN char * stb_dupreplace(char *s, char *find, char *replace); +STB_EXTERN void stb_replaceinplace(char *s, char *find, char *replace); +STB_EXTERN char * stb_splitpath(char *output, char *src, int flag); +STB_EXTERN char * stb_splitpathdup(char *src, int flag); +STB_EXTERN char * stb_replacedir(char *output, char *src, char *dir); +STB_EXTERN char * stb_replaceext(char *output, char *src, char *ext); +STB_EXTERN void stb_fixpath(char *path); +STB_EXTERN char * stb_shorten_path_readable(char *path, int max_len); +STB_EXTERN int stb_suffix (char *s, char *t); +STB_EXTERN int stb_suffixi(char *s, char *t); +STB_EXTERN int stb_prefix (char *s, char *t); +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 const 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); +STB_EXTERN char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out); +STB_EXTERN char **stb_tokens_allowempty(char *src, char *delimit, int *count); +STB_EXTERN char **stb_tokens_stripwhite(char *src, char *delimit, int *count); +STB_EXTERN char **stb_tokens_withdelim(char *src, char *delimit, int *count); +STB_EXTERN char **stb_tokens_quoted(char *src, char *delimit, int *count); +// with 'quoted', allow delimiters to appear inside quotation marks, and don't +// strip whitespace inside them (and we delete the quotation marks unless they +// appear back to back, in which case they're considered escaped) +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION +#include + +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; +} + +const char *stb_plural(int n) +{ + return n == 1 ? "" : "s"; +} + +int stb_prefix(char *s, char *t) +{ + while (*t) + if (*s++ != *t++) + return 0; + return 1; +} + +int stb_prefix_count(char *s, char *t) +{ + int c=0; + while (*t) { + if (*s++ != *t++) + break; + ++c; + } + return c; +} + +int stb_suffix(char *s, char *t) +{ + size_t n = strlen(s); + size_t m = strlen(t); + if (m <= n) + return 0 == strcmp(s+n-m, t); + else + return 0; +} + +int stb_suffixi(char *s, char *t) +{ + size_t n = strlen(s); + size_t m = strlen(t); + if (m <= n) + return 0 == stb_stricmp(s+n-m, t); + else + return 0; +} + +// originally I was using this table so that I could create known sentinel +// values--e.g. change whitetable[0] to be true if I was scanning for whitespace, +// and false if I was scanning for nonwhite. I don't appear to be using that +// functionality anymore (I do for tokentable, though), so just replace it +// with isspace() +char *stb_skipwhite(char *s) +{ + while (isspace((unsigned char) *s)) ++s; + return s; +} + +char *stb_skipnewline(char *s) +{ + if (s[0] == '\r' || s[0] == '\n') { + if (s[0]+s[1] == '\r' + '\n') ++s; + ++s; + } + return s; +} + +char *stb_trimwhite(char *s) +{ + int i,n; + s = stb_skipwhite(s); + n = (int) strlen(s); + for (i=n-1; i >= 0; --i) + if (!isspace(s[i])) + break; + s[i+1] = 0; + return s; +} + +char *stb_strncpy(char *s, char *t, int n) +{ + strncpy(s,t,n); + s[n-1] = 0; + return s; +} + +char *stb_substr(char *t, int n) +{ + char *a; + int z = (int) strlen(t); + if (z < n) n = z; + a = (char *) malloc(n+1); + strncpy(a,t,n); + a[n] = 0; + return a; +} + +char *stb_duplower(char *s) +{ + char *p = strdup(s), *q = p; + while (*q) { + *q = tolower(*q); + ++q; + } + return p; +} + +void stb_tolower(char *s) +{ + while (*s) { + *s = tolower(*s); + ++s; + } +} + +char *stb_strchr2(char *s, char x, char y) +{ + for(; *s; ++s) + if (*s == x || *s == y) + return s; + return NULL; +} + +char *stb_strrchr2(char *s, char x, char y) +{ + char *r = NULL; + for(; *s; ++s) + if (*s == x || *s == y) + r = s; + return r; +} + +char *stb_strichr(char *s, char t) +{ + if (tolower(t) == toupper(t)) + return strchr(s,t); + return stb_strchr2(s, (char) tolower(t), (char) toupper(t)); +} + +char *stb_stristr(char *s, char *t) +{ + size_t n = strlen(t); + char *z; + if (n==0) return s; + while ((z = stb_strichr(s, *t)) != NULL) { + if (0==stb_strnicmp(z, t, n)) + return z; + s = z+1; + } + return NULL; +} + +static char *stb_strtok_raw(char *output, char *src, char *delimit, int keep, int invert) +{ + if (invert) { + while (*src && strchr(delimit, *src) != NULL) { + *output++ = *src++; + } + } else { + while (*src && strchr(delimit, *src) == NULL) { + *output++ = *src++; + } + } + *output = 0; + if (keep) + return src; + else + return *src ? src+1 : src; +} + +char *stb_strtok(char *output, char *src, char *delimit) +{ + return stb_strtok_raw(output, src, delimit, 0, 0); +} + +char *stb_strtok_keep(char *output, char *src, char *delimit) +{ + return stb_strtok_raw(output, src, delimit, 1, 0); +} + +char *stb_strtok_invert(char *output, char *src, char *delimit) +{ + return stb_strtok_raw(output, src, delimit, 1,1); +} + +static char **stb_tokens_raw(char *src_, char *delimit, int *count, + int stripwhite, int allow_empty, char *start, char *end) +{ + int nested = 0; + unsigned char *src = (unsigned char *) src_; + static char stb_tokentable[256]; // rely on static initializion to 0 + static char stable[256],etable[256]; + char *out; + char **result; + int num=0; + unsigned char *s; + + s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 1; + if (start) { + s = (unsigned char *) start; while (*s) stable[*s++] = 1; + s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1; + s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1; + } + stable[0] = 1; + + // two passes through: the first time, counting how many + s = (unsigned char *) src; + while (*s) { + // state: just found delimiter + // skip further delimiters + if (!allow_empty) { + stb_tokentable[0] = 0; + while (stb_tokentable[*s]) + ++s; + if (!*s) break; + } + ++num; + // skip further non-delimiters + stb_tokentable[0] = 1; + if (stripwhite == 2) { // quoted strings + while (!stb_tokentable[*s]) { + if (*s != '"') + ++s; + else { + ++s; + if (*s == '"') + ++s; // "" -> ", not start a string + else { + // begin a string + while (*s) { + if (s[0] == '"') { + if (s[1] == '"') s += 2; // "" -> " + else { ++s; break; } // terminating " + } else + ++s; + } + } + } + } + } else + while (nested || !stb_tokentable[*s]) { + if (stable[*s]) { + if (!*s) break; + if (end ? etable[*s] : nested) + --nested; + else + ++nested; + } + ++s; + } + if (allow_empty) { + if (*s) ++s; + } + } + // now num has the actual count... malloc our output structure + // need space for all the strings: strings won't be any longer than + // original input, since for every '\0' there's at least one delimiter + result = (char **) malloc(sizeof(*result) * (num+1) + (s-src+1)); + if (result == NULL) return result; + out = (char *) (result + (num+1)); + // second pass: copy out the data + s = (unsigned char *) src; + num = 0; + nested = 0; + while (*s) { + char *last_nonwhite; + // state: just found delimiter + // skip further delimiters + if (!allow_empty) { + stb_tokentable[0] = 0; + if (stripwhite) + while (stb_tokentable[*s] || isspace(*s)) + ++s; + else + while (stb_tokentable[*s]) + ++s; + } else if (stripwhite) { + while (isspace(*s)) ++s; + } + if (!*s) break; + // we're past any leading delimiters and whitespace + result[num] = out; + ++num; + // copy non-delimiters + stb_tokentable[0] = 1; + last_nonwhite = out-1; + if (stripwhite == 2) { + while (!stb_tokentable[*s]) { + if (*s != '"') { + if (!isspace(*s)) last_nonwhite = out; + *out++ = *s++; + } else { + ++s; + if (*s == '"') { + if (!isspace(*s)) last_nonwhite = out; + *out++ = *s++; // "" -> ", not start string + } else { + // begin a quoted string + while (*s) { + if (s[0] == '"') { + if (s[1] == '"') { *out++ = *s; s += 2; } + else { ++s; break; } // terminating " + } else + *out++ = *s++; + } + last_nonwhite = out-1; // all in quotes counts as non-white + } + } + } + } else { + while (nested || !stb_tokentable[*s]) { + if (!isspace(*s)) last_nonwhite = out; + if (stable[*s]) { + if (!*s) break; + if (end ? etable[*s] : nested) + --nested; + else + ++nested; + } + *out++ = *s++; + } + } + + if (stripwhite) // rewind to last non-whitespace char + out = last_nonwhite+1; + *out++ = '\0'; + + if (*s) ++s; // skip delimiter + } + s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 0; + if (start) { + s = (unsigned char *) start; while (*s) stable[*s++] = 1; + s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1; + s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1; + } + if (count != NULL) *count = num; + result[num] = 0; + return result; +} + +char **stb_tokens(char *src, char *delimit, int *count) +{ + return stb_tokens_raw(src,delimit,count,0,0,0,0); +} + +char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out) +{ + return stb_tokens_raw(src,delimit,count,0,0,nest_in,nest_out); +} + +char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out) +{ + return stb_tokens_raw(src,delimit,count,0,1,nest_in,nest_out); +} + +char **stb_tokens_allowempty(char *src, char *delimit, int *count) +{ + return stb_tokens_raw(src,delimit,count,0,1,0,0); +} + +char **stb_tokens_stripwhite(char *src, char *delimit, int *count) +{ + return stb_tokens_raw(src,delimit,count,1,1,0,0); +} + +char **stb_tokens_quoted(char *src, char *delimit, int *count) +{ + return stb_tokens_raw(src,delimit,count,2,1,0,0); +} + +char *stb_dupreplace(char *src, char *find, char *replace) +{ + size_t len_find = strlen(find); + size_t len_replace = strlen(replace); + int count = 0; + + char *s,*p,*q; + + s = strstr(src, find); + if (s == NULL) return strdup(src); + do { + ++count; + s = strstr(s + len_find, find); + } while (s != NULL); + + p = (char *) malloc(strlen(src) + count * (len_replace - len_find) + 1); + if (p == NULL) return p; + q = p; + s = src; + for (;;) { + char *t = strstr(s, find); + if (t == NULL) { + strcpy(q,s); + assert(strlen(p) == strlen(src) + count*(len_replace-len_find)); + return p; + } + memcpy(q, s, t-s); + q += t-s; + memcpy(q, replace, len_replace); + q += len_replace; + s = t + len_find; + } +} + +void stb_replaceinplace(char *src, char *find, char *replace) +{ + size_t len_find = strlen(find); + size_t len_replace = strlen(replace); + int delta; + + char *s,*p,*q; + + delta = len_replace - len_find; + assert(delta <= 0); + if (delta > 0) return; + + p = strstr(src, find); + if (p == NULL) return; + + s = q = p; + while (*s) { + memcpy(q, replace, len_replace); + p += len_find; + q += len_replace; + s = strstr(p, find); + if (s == NULL) s = p + strlen(p); + memmove(q, p, s-p); + q += s-p; + p = s; + } + *q = 0; +} + +void stb_fixpath(char *path) +{ + for(; *path; ++path) + if (*path == '\\') + *path = '/'; +} + +void stb__add_section(char *buffer, char *data, int curlen, int newlen) +{ + if (newlen < curlen) { + int z1 = newlen >> 1, z2 = newlen-z1; + memcpy(buffer, data, z1-1); + buffer[z1-1] = '.'; + buffer[z1-0] = '.'; + memcpy(buffer+z1+1, data+curlen-z2+1, z2-1); + } else + memcpy(buffer, data, curlen); +} + +char * stb_shorten_path_readable(char *path, int len) +{ + static char buffer[1024]; + int n = strlen(path),n1,n2,r1,r2; + char *s; + if (n <= len) return path; + if (len > 1024) return path; + s = stb_strrchr2(path, '/', '\\'); + if (s) { + n1 = s - path + 1; + n2 = n - n1; + ++s; + } else { + n1 = 0; + n2 = n; + s = path; + } + // now we need to reduce r1 and r2 so that they fit in len + if (n1 < len>>1) { + r1 = n1; + r2 = len - r1; + } else if (n2 < len >> 1) { + r2 = n2; + r1 = len - r2; + } else { + r1 = n1 * len / n; + r2 = n2 * len / n; + if (r1 < len>>2) r1 = len>>2, r2 = len-r1; + if (r2 < len>>2) r2 = len>>2, r1 = len-r2; + } + assert(r1 <= n1 && r2 <= n2); + if (n1) + stb__add_section(buffer, path, n1, r1); + stb__add_section(buffer+r1, s, n2, r2); + buffer[len] = 0; + return buffer; +} + +static char *stb__splitpath_raw(char *buffer, char *path, int flag) +{ + int len=0,x,y, n = (int) strlen(path), f1,f2; + char *s = stb_strrchr2(path, '/', '\\'); + char *t = strrchr(path, '.'); + if (s && t && t < s) t = NULL; + if (s) ++s; + + if (flag == STB_EXT_NO_PERIOD) + flag |= STB_EXT; + + if (!(flag & (STB_PATH | STB_FILE | STB_EXT))) return NULL; + + f1 = s == NULL ? 0 : s-path; // start of filename + f2 = t == NULL ? n : t-path; // just past end of filename + + if (flag & STB_PATH) { + x = 0; if (f1 == 0 && flag == STB_PATH) len=2; + } else if (flag & STB_FILE) { + x = f1; + } else { + x = f2; + if (flag & STB_EXT_NO_PERIOD) + if (buffer[x] == '.') + ++x; + } + + if (flag & STB_EXT) + y = n; + else if (flag & STB_FILE) + y = f2; + else + y = f1; + + if (buffer == NULL) { + buffer = (char *) malloc(y-x + len + 1); + if (!buffer) return NULL; + } + + if (len) { strcpy(buffer, "./"); return buffer; } + strncpy(buffer, path+x, y-x); + buffer[y-x] = 0; + return buffer; +} + +char *stb_splitpath(char *output, char *src, int flag) +{ + return stb__splitpath_raw(output, src, flag); +} + +char *stb_splitpathdup(char *src, int flag) +{ + return stb__splitpath_raw(NULL, src, flag); +} + +char *stb_replacedir(char *output, char *src, char *dir) +{ + char buffer[4096]; + stb_splitpath(buffer, src, STB_FILE | STB_EXT); + if (dir) + sprintf(output, "%s/%s", dir, buffer); + else + strcpy(output, buffer); + return output; +} + +char *stb_replaceext(char *output, char *src, char *ext) +{ + char buffer[4096]; + stb_splitpath(buffer, src, STB_PATH | STB_FILE); + if (ext) + sprintf(output, "%s.%s", buffer, ext[0] == '.' ? ext+1 : ext); + else + strcpy(output, buffer); + return output; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// stb_arr +// +// An stb_arr is directly useable as a pointer (use the actual type in your +// definition), but when it resizes, it returns a new pointer and you can't +// use the old one, so you have to be careful to copy-in-out as necessary. +// +// Use a NULL pointer as a 0-length array. +// +// float *my_array = NULL, *temp; +// +// // add elements on the end one at a time +// stb_arr_push(my_array, 0.0f); +// stb_arr_push(my_array, 1.0f); +// stb_arr_push(my_array, 2.0f); +// +// assert(my_array[1] == 2.0f); +// +// // add an uninitialized element at the end, then assign it +// *stb_arr_add(my_array) = 3.0f; +// +// // add three uninitialized elements at the end +// temp = stb_arr_addn(my_array,3); +// temp[0] = 4.0f; +// temp[1] = 5.0f; +// temp[2] = 6.0f; +// +// assert(my_array[5] == 5.0f); +// +// // remove the last one +// stb_arr_pop(my_array); +// +// assert(stb_arr_len(my_array) == 6); + + +#ifndef STB_INCLUDE_STB_LIB_H + +// simple functions written on top of other functions +#define stb_arr_empty(a) ( stb_arr_len(a) == 0 ) +#define stb_arr_add(a) ( stb_arr_addn((a),1) ) +#define stb_arr_push(a,v) ( *stb_arr_add(a)=(v) ) + +typedef struct +{ + int len, limit; + unsigned int signature; + unsigned int padding; // make it a multiple of 16 so preserve alignment mod 16 +} stb__arr; + +#define stb_arr_signature 0x51bada7b // ends with 0123 in decimal + +// access the header block stored before the data +#define stb_arrhead(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1) +#define stb_arrhead2(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1) + +#ifdef STB_DEBUG +#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) ((void) 0) +#define stb_arr_check2(a) ((void) 0) +#endif + +// ARRAY LENGTH + +// get the array length; special case if pointer is NULL +#define stb_arr_len(a) (a ? stb_arrhead(a)->len : 0) +#define stb_arr_len2(a) ((stb__arr *) (a) ? stb_arrhead2(a)->len : 0) +#define stb_arr_lastn(a) (stb_arr_len(a)-1) + +// check whether a given index is valid -- tests 0 <= i < stb_arr_len(a) +#define stb_arr_valid(a,i) (a ? (int) (i) < stb_arrhead(a)->len : 0) + +// change the array length so is is exactly N entries long, creating +// uninitialized entries as needed +#define stb_arr_setlen(a,n) \ + (stb__arr_setlen((void **) &(a), sizeof(a[0]), (n))) + +// change the array length so that N is a valid index (that is, so +// it is at least N entries long), creating uninitialized entries as needed +#define stb_arr_makevalid(a,n) \ + (stb_arr_len(a) < (n)+1 ? stb_arr_setlen(a,(n)+1),(a) : (a)) + +// remove the last element of the array, returning it +#define stb_arr_pop(a) ((stb_arr_check(a), (a))[--stb_arrhead(a)->len]) + +// access the last element in the array +#define stb_arr_last(a) ((stb_arr_check(a), (a))[stb_arr_len(a)-1]) + +// is iterator at end of list? +#define stb_arr_end(a,i) ((i) >= &(a)[stb_arr_len(a)]) + +// (internal) change the allocated length of the array +#define stb_arr__grow(a,n) (stb_arr_check(a), stb_arrhead(a)->len += (n)) + +// add N new unitialized elements to the end of the array +#define stb_arr__addn(a,n) /*lint --e(826)*/ \ + ((stb_arr_len(a)+(n) > stb_arrcurmax(a)) \ + ? (stb__arr_addlen((void **) &(a),sizeof(*a),(n)),0) \ + : ((stb_arr__grow(a,n), 0))) + +// add N new unitialized elements to the end of the array, and return +// a pointer to the first new one +#define stb_arr_addn(a,n) (stb_arr__addn((a),n),(a)+stb_arr_len(a)-(n)) + +// add N new uninitialized elements starting at index 'i' +#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, 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)) + +// delete the i'th element +#define stb_arr_delete(a,i) stb_arr_deleten(a,i,1) + +// delete the i'th element, swapping down from the end +#define stb_arr_fastdelete(a,i) \ + (stb_swap(&a[i], &a[stb_arrhead(a)->len-1], sizeof(*a)), stb_arr_pop(a)) + + +// ARRAY STORAGE + +// get the array maximum storage; special case if NULL +#define stb_arrcurmax(a) (a ? stb_arrhead(a)->limit : 0) +#define stb_arrcurmax2(a) (a ? stb_arrhead2(a)->limit : 0) + +// set the maxlength of the array to n in anticipation of further growth +#define stb_arr_setsize(a,n) (stb_arr_check(a), stb__arr_setsize((void **) &(a),sizeof((a)[0]),n)) + +// make sure maxlength is large enough for at least N new allocations +#define stb_arr_atleast(a,n) (stb_arr_len(a)+(n) > stb_arrcurmax(a) \ + ? stb_arr_setsize((a), (n)) : 0) + +// make a copy of a given array (copies contents via 'memcpy'!) +#define stb_arr_copy(a) stb__arr_copy(a, sizeof((a)[0])) + +// compute the storage needed to store all the elements of the array +#define stb_arr_storage(a) (stb_arr_len(a) * sizeof((a)[0])) + +#define stb_arr_for(v,arr) for((v)=(arr); (v) < (arr)+stb_arr_len(arr); ++(v)) + +// IMPLEMENTATION + +STB_EXTERN void stb_arr_free_(void **p); +STB_EXTERN void *stb__arr_copy_(void *p, int elem_size); +STB_EXTERN void stb__arr_setsize_(void **p, int size, int limit); +STB_EXTERN void stb__arr_setlen_(void **p, int size, int newlen); +STB_EXTERN void stb__arr_addlen_(void **p, int size, int addlen); +STB_EXTERN void stb__arr_deleten_(void **p, int size, int loc, int n); +STB_EXTERN void stb__arr_insertn_(void **p, int size, int loc, int n); + +#define stb_arr_free(p) stb_arr_free_((void **) &(p)) + +#ifndef STBLIB_MALLOC_WRAPPER // @Todo + #define stb__arr_setsize stb__arr_setsize_ + #define stb__arr_setlen stb__arr_setlen_ + #define stb__arr_addlen stb__arr_addlen_ + #define stb__arr_deleten stb__arr_deleten_ + #define stb__arr_insertn stb__arr_insertn_ + #define stb__arr_copy stb__arr_copy_ +#else + #define stb__arr_addlen(p,s,n) stb__arr_addlen_(p,s,n,__FILE__,__LINE__) + #define stb__arr_setlen(p,s,n) stb__arr_setlen_(p,s,n,__FILE__,__LINE__) + #define stb__arr_setsize(p,s,n) stb__arr_setsize_(p,s,n,__FILE__,__LINE__) + #define stb__arr_deleten(p,s,i,n) stb__arr_deleten_(p,s,i,n,__FILE__,__LINE__) + #define stb__arr_insertn(p,s,i,n) stb__arr_insertn_(p,s,i,n,__FILE__,__LINE__) + #define stb__arr_copy(p,s) stb__arr_copy_(p,s,__FILE__,__LINE__) +#endif +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION +void stb_arr_malloc(void **target, void *context) +{ + stb__arr *q = (stb__arr *) malloc(sizeof(*q)); + q->len = q->limit = 0; + q->signature = stb_arr_signature; + *target = (void *) (q+1); +} + +static void * stb__arr_malloc(int size) +{ + return malloc(size); +} + +void * stb__arr_copy_(void *p, int elem_size) +{ + stb__arr *q; + if (p == NULL) return p; + q = (stb__arr *) malloc(sizeof(*q) + elem_size * stb_arrhead2(p)->limit); + stb_arr_check2(p); + memcpy(q, stb_arrhead2(p), sizeof(*q) + elem_size * stb_arrhead2(p)->len); + return q+1; +} + +void stb_arr_free_(void **pp) +{ + void *p = *pp; + stb_arr_check2(p); + if (p) { + stb__arr *q = stb_arrhead2(p); + free(q); + } + *pp = NULL; +} + +static void stb__arrsize_(void **pp, int size, int limit, int len) +{ + void *p = *pp; + stb__arr *a; + stb_arr_check2(p); + if (p == NULL) { + if (len == 0 && size == 0) return; + a = (stb__arr *) stb__arr_malloc(sizeof(*a) + size*limit); + a->limit = limit; + a->len = len; + a->signature = stb_arr_signature; + } else { + a = stb_arrhead2(p); + a->len = len; + if (a->limit < limit) { + void *p; + if (a->limit >= 4 && limit < a->limit * 2) + limit = a->limit * 2; + p = realloc(a, sizeof(*a) + limit*size); + if (p) { + a = (stb__arr *) p; + a->limit = limit; + } else { + // throw an error! + } + } + } + a->len = a->len < a->limit ? a->len : a->limit; + *pp = a+1; +} + +void stb__arr_setsize_(void **pp, int size, int limit) +{ + void *p = *pp; + stb_arr_check2(p); + stb__arrsize_(pp, size, limit, stb_arr_len2(p)); +} + +void stb__arr_setlen_(void **pp, int size, int newlen) +{ + void *p = *pp; + stb_arr_check2(p); + if (stb_arrcurmax2(p) < newlen || p == NULL) { + stb__arrsize_(pp, size, newlen, newlen); + } else { + stb_arrhead2(p)->len = newlen; + } +} + +void stb__arr_addlen_(void **p, int size, int addlen) +{ + stb__arr_setlen_(p, size, stb_arr_len2(*p) + addlen); +} + +void stb__arr_insertn_(void **pp, int size, int i, int n) +{ + void *p = *pp; + if (n) { + int z; + + if (p == NULL) { + stb__arr_addlen_(pp, size, n); + return; + } + + z = stb_arr_len2(p); + stb__arr_addlen_(&p, size, n); + memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-i)); + } + *pp = p; +} + +void stb__arr_deleten_(void **pp, int size, int i, int n) +{ + void *p = *pp; + if (n) { + memmove((char *) p + i*size, (char *) p + (i+n)*size, size * (stb_arr_len2(p)-(i+n))); + stb_arrhead2(p)->len -= n; + } + *pp = p; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Hashing +// +// typical use for this is to make a power-of-two hash table. +// +// let N = size of table (2^n) +// let H = stb_hash(str) +// let S = stb_rehash(H) | 1 +// +// then hash probe sequence P(i) for i=0..N-1 +// P(i) = (H + S*i) & (N-1) +// +// the idea is that H has 32 bits of hash information, but the +// table has only, say, 2^20 entries so only uses 20 of the bits. +// then by rehashing the original H we get 2^12 different probe +// sequences for a given initial probe location. (So it's optimal +// for 64K tables and its optimality decreases past that.) +// +// ok, so I've added something that generates _two separate_ +// 32-bit hashes simultaneously which should scale better to +// very large tables. + +#ifndef STB_INCLUDE_STB_LIB_H +STB_EXTERN unsigned int stb_hash(char *str); +STB_EXTERN unsigned int stb_hashptr(void *p); +STB_EXTERN unsigned int stb_hashlen(char *str, int len); +STB_EXTERN unsigned int stb_rehash_improved(unsigned int v); +STB_EXTERN unsigned int stb_hash_fast(void *p, int len); +STB_EXTERN unsigned int stb_hash2(char *str, unsigned int *hash2_ptr); +STB_EXTERN unsigned int stb_hash_number(unsigned int hash); + +#define stb_rehash(x) ((x) + ((x) >> 6) + ((x) >> 19)) +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION +unsigned int stb_hash(char *str) +{ + unsigned int hash = 0; + while (*str) + hash = (hash << 7) + (hash >> 25) + *str++; + return hash + (hash >> 16); +} + +unsigned int stb_hashlen(char *str, int len) +{ + unsigned int hash = 0; + while (len-- > 0 && *str) + hash = (hash << 7) + (hash >> 25) + *str++; + return hash + (hash >> 16); +} + +unsigned int stb_hashptr(void *p) +{ + unsigned int x = (unsigned int)(size_t) p; + + // typically lacking in low bits and high bits + x = stb_rehash(x); + x += x << 16; + + // pearson's shuffle + x ^= x << 3; + x += x >> 5; + x ^= x << 2; + x += x >> 15; + x ^= x << 10; + return stb_rehash(x); +} + +unsigned int stb_rehash_improved(unsigned int v) +{ + return stb_hashptr((void *)(size_t) v); +} + +unsigned int stb_hash2(char *str, unsigned int *hash2_ptr) +{ + unsigned int hash1 = 0x3141592c; + unsigned int hash2 = 0x77f044ed; + while (*str) { + hash1 = (hash1 << 7) + (hash1 >> 25) + *str; + hash2 = (hash2 << 11) + (hash2 >> 21) + *str; + ++str; + } + *hash2_ptr = hash2 + (hash1 >> 16); + return hash1 + (hash2 >> 16); +} + +// Paul Hsieh hash +#define stb__get16_slow(p) ((p)[0] + ((p)[1] << 8)) +#if defined(_MSC_VER) + #define stb__get16(p) (*((unsigned short *) (p))) +#else + #define stb__get16(p) stb__get16_slow(p) +#endif + +unsigned int stb_hash_fast(void *p, int len) +{ + unsigned char *q = (unsigned char *) p; + unsigned int hash = len; + + if (len <= 0 || q == NULL) return 0; + + /* Main loop */ + if (((int)(size_t) q & 1) == 0) { + for (;len > 3; len -= 4) { + unsigned int val; + hash += stb__get16(q); + val = (stb__get16(q+2) << 11); + hash = (hash << 16) ^ hash ^ val; + q += 4; + hash += hash >> 11; + } + } else { + for (;len > 3; len -= 4) { + unsigned int val; + hash += stb__get16_slow(q); + val = (stb__get16_slow(q+2) << 11); + hash = (hash << 16) ^ hash ^ val; + q += 4; + hash += hash >> 11; + } + } + + /* Handle end cases */ + switch (len) { + case 3: hash += stb__get16_slow(q); + hash ^= hash << 16; + hash ^= q[2] << 18; + hash += hash >> 11; + break; + case 2: hash += stb__get16_slow(q); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += q[0]; + hash ^= hash << 10; + hash += hash >> 1; + break; + case 0: break; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; +} + +unsigned int stb_hash_number(unsigned int hash) +{ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Instantiated data structures +// +// This is an attempt to implement a templated data structure. +// +// Hash table: call stb_define_hash(TYPE,N,KEY,K1,K2,HASH,VALUE) +// TYPE -- will define a structure type containing the hash table +// N -- the name, will prefix functions named: +// N create +// N destroy +// N get +// N set, N add, N update, +// N remove +// KEY -- the type of the key. 'x == y' must be valid +// K1,K2 -- keys never used by the app, used as flags in the hashtable +// HASH -- a piece of code ending with 'return' that hashes key 'k' +// VALUE -- the type of the value. 'x = y' must be valid +// +// Note that stb_define_hash_base can be used to define more sophisticated +// hash tables, e.g. those that make copies of the key or use special +// comparisons (e.g. strcmp). + +#define STB_(prefix,name) stb__##prefix##name +#define STB__(prefix,name) prefix##name +#define STB__use(x) x +#define STB__skip(x) + +#define stb_declare_hash(PREFIX,TYPE,N,KEY,VALUE) \ + typedef struct stb__st_##TYPE TYPE;\ + PREFIX int STB__(N, init)(TYPE *h, int count);\ + PREFIX int STB__(N, memory_usage)(TYPE *h);\ + PREFIX TYPE * STB__(N, create)(void);\ + PREFIX TYPE * STB__(N, copy)(TYPE *h);\ + PREFIX void STB__(N, destroy)(TYPE *h);\ + PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v);\ + PREFIX VALUE STB__(N,get)(TYPE *a, KEY k);\ + PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v);\ + PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v);\ + PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v);\ + PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v); + +#define STB_nocopy(x) (x) +#define STB_nodelete(x) 0 +#define STB_nofields +#define STB_nonullvalue(x) +#define STB_nullvalue(x) x +#define STB_safecompare(x) x +#define STB_nosafe(x) +#define STB_noprefix + +#ifdef __GNUC__ +#define STB__nogcc(x) +#else +#define STB__nogcc(x) x +#endif + +#define stb_define_hash_base(PREFIX,TYPE,FIELDS,N,NC,LOAD_FACTOR, \ + KEY,EMPTY,DEL,COPY,DISPOSE,SAFE, \ + VCOMPARE,CCOMPARE,HASH, \ + VALUE,HASVNULL,VNULL) \ + \ +typedef struct \ +{ \ + KEY k; \ + VALUE v; \ +} STB_(N,_hashpair); \ + \ +STB__nogcc( typedef struct stb__st_##TYPE TYPE; ) \ +struct stb__st_##TYPE { \ + FIELDS \ + STB_(N,_hashpair) *table; \ + unsigned int mask; \ + int count, limit; \ + int deleted; \ + \ + int delete_threshhold; \ + int grow_threshhold; \ + int shrink_threshhold; \ + unsigned char alloced, has_empty, has_del; \ + VALUE ev; VALUE dv; \ +}; \ + \ +static unsigned int STB_(N, hash)(KEY k) \ +{ \ + HASH \ +} \ + \ +PREFIX int STB__(N, init)(TYPE *h, int count) \ +{ \ + int i; \ + if (count < 4) count = 4; \ + h->limit = count; \ + h->count = 0; \ + h->mask = count-1; \ + h->deleted = 0; \ + h->grow_threshhold = (int) (count * LOAD_FACTOR); \ + h->has_empty = h->has_del = 0; \ + h->alloced = 0; \ + if (count <= 64) \ + h->shrink_threshhold = 0; \ + else \ + h->shrink_threshhold = (int) (count * (LOAD_FACTOR/2.25)); \ + h->delete_threshhold = (int) (count * (1-LOAD_FACTOR)/2); \ + h->table = (STB_(N,_hashpair)*) malloc(sizeof(h->table[0]) * count); \ + if (h->table == NULL) return 0; \ + /* ideally this gets turned into a memset32 automatically */ \ + for (i=0; i < count; ++i) \ + h->table[i].k = EMPTY; \ + return 1; \ +} \ + \ +PREFIX int STB__(N, memory_usage)(TYPE *h) \ +{ \ + return sizeof(*h) + h->limit * sizeof(h->table[0]); \ +} \ + \ +PREFIX TYPE * STB__(N, create)(void) \ +{ \ + TYPE *h = (TYPE *) malloc(sizeof(*h)); \ + if (h) { \ + if (STB__(N, init)(h, 16)) \ + h->alloced = 1; \ + else { free(h); h=NULL; } \ + } \ + return h; \ +} \ + \ +PREFIX void STB__(N, destroy)(TYPE *a) \ +{ \ + int i; \ + for (i=0; i < a->limit; ++i) \ + if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k, DEL)) \ + DISPOSE(a->table[i].k); \ + free(a->table); \ + if (a->alloced) \ + free(a); \ +} \ + \ +static void STB_(N, rehash)(TYPE *a, int count); \ + \ +PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v) \ +{ \ + unsigned int h = STB_(N, hash)(k); \ + unsigned int n = h & a->mask, s; \ + if (CCOMPARE(k,EMPTY)){ if (a->has_empty) *v = a->ev; return a->has_empty;}\ + if (CCOMPARE(k,DEL)) { if (a->has_del ) *v = a->dv; return a->has_del; }\ + if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \ + SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \ + if (VCOMPARE(a->table[n].k,k)) { *v = a->table[n].v; return 1; } \ + s = stb_rehash(h) | 1; \ + for(;;) { \ + n = (n + s) & a->mask; \ + if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \ + SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \ + if (VCOMPARE(a->table[n].k,k)) \ + { *v = a->table[n].v; return 1; } \ + } \ +} \ + \ +HASVNULL( \ + PREFIX VALUE STB__(N,get)(TYPE *a, KEY k) \ + { \ + VALUE v; \ + if (STB__(N,get_flag)(a,k,&v)) return v; \ + else return VNULL; \ + } \ +) \ + \ +PREFIX int STB__(N,getkey)(TYPE *a, KEY k, KEY *kout) \ +{ \ + unsigned int h = STB_(N, hash)(k); \ + unsigned int n = h & a->mask, s; \ + if (CCOMPARE(k,EMPTY)||CCOMPARE(k,DEL)) return 0; \ + if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \ + SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \ + if (VCOMPARE(a->table[n].k,k)) { *kout = a->table[n].k; return 1; } \ + s = stb_rehash(h) | 1; \ + for(;;) { \ + n = (n + s) & a->mask; \ + if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \ + SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \ + if (VCOMPARE(a->table[n].k,k)) \ + { *kout = a->table[n].k; return 1; } \ + } \ +} \ + \ +static int STB_(N,addset)(TYPE *a, KEY k, VALUE v, \ + int allow_new, int allow_old, int copy) \ +{ \ + unsigned int h = STB_(N, hash)(k); \ + unsigned int n = h & a->mask; \ + int b = -1; \ + if (CCOMPARE(k,EMPTY)) { \ + if (a->has_empty ? allow_old : allow_new) { \ + n=a->has_empty; a->ev = v; a->has_empty = 1; return !n; \ + } else return 0; \ + } \ + if (CCOMPARE(k,DEL)) { \ + if (a->has_del ? allow_old : allow_new) { \ + n=a->has_del; a->dv = v; a->has_del = 1; return !n; \ + } else return 0; \ + } \ + if (!CCOMPARE(a->table[n].k, EMPTY)) { \ + unsigned int s; \ + if (CCOMPARE(a->table[n].k, DEL)) \ + b = n; \ + else if (VCOMPARE(a->table[n].k,k)) { \ + if (allow_old) \ + a->table[n].v = v; \ + return !allow_new; \ + } \ + s = stb_rehash(h) | 1; \ + for(;;) { \ + n = (n + s) & a->mask; \ + if (CCOMPARE(a->table[n].k, EMPTY)) break; \ + if (CCOMPARE(a->table[n].k, DEL)) { \ + if (b < 0) b = n; \ + } else if (VCOMPARE(a->table[n].k,k)) { \ + if (allow_old) \ + a->table[n].v = v; \ + return !allow_new; \ + } \ + } \ + } \ + if (!allow_new) return 0; \ + if (b < 0) b = n; else --a->deleted; \ + a->table[b].k = copy ? COPY(k) : k; \ + a->table[b].v = v; \ + ++a->count; \ + if (a->count > a->grow_threshhold) \ + STB_(N,rehash)(a, a->limit*2); \ + return 1; \ +} \ + \ +PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,1,1);}\ +PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,0,1);}\ +PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v){return STB_(N,addset)(a,k,v,0,1,1);}\ + \ +PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v) \ +{ \ + unsigned int h = STB_(N, hash)(k); \ + unsigned int n = h & a->mask, s; \ + if (CCOMPARE(k,EMPTY)) { if (a->has_empty) { if(v)*v = a->ev; a->has_empty=0; return 1; } return 0; } \ + if (CCOMPARE(k,DEL)) { if (a->has_del ) { if(v)*v = a->dv; a->has_del =0; return 1; } return 0; } \ + if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \ + if (SAFE(CCOMPARE(a->table[n].k,DEL) || ) !VCOMPARE(a->table[n].k,k)) { \ + s = stb_rehash(h) | 1; \ + for(;;) { \ + n = (n + s) & a->mask; \ + if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \ + SAFE(if (CCOMPARE(a->table[n].k, DEL)) continue;) \ + if (VCOMPARE(a->table[n].k,k)) break; \ + } \ + } \ + DISPOSE(a->table[n].k); \ + a->table[n].k = DEL; \ + --a->count; \ + ++a->deleted; \ + if (v != NULL) \ + *v = a->table[n].v; \ + if (a->count < a->shrink_threshhold) \ + STB_(N, rehash)(a, a->limit >> 1); \ + else if (a->deleted > a->delete_threshhold) \ + STB_(N, rehash)(a, a->limit); \ + return 1; \ +} \ + \ +PREFIX TYPE * STB__(NC, copy)(TYPE *a) \ +{ \ + int i; \ + TYPE *h = (TYPE *) malloc(sizeof(*h)); \ + if (!h) return NULL; \ + if (!STB__(N, init)(h, a->limit)) { free(h); return NULL; } \ + h->count = a->count; \ + h->deleted = a->deleted; \ + h->alloced = 1; \ + h->ev = a->ev; h->dv = a->dv; \ + h->has_empty = a->has_empty; h->has_del = a->has_del; \ + memcpy(h->table, a->table, h->limit * sizeof(h->table[0])); \ + for (i=0; i < a->limit; ++i) \ + if (!CCOMPARE(h->table[i].k,EMPTY) && !CCOMPARE(h->table[i].k,DEL)) \ + h->table[i].k = COPY(h->table[i].k); \ + return h; \ +} \ + \ +static void STB_(N, rehash)(TYPE *a, int count) \ +{ \ + int i; \ + TYPE b; \ + STB__(N, init)(&b, count); \ + for (i=0; i < a->limit; ++i) \ + if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k,DEL)) \ + STB_(N,addset)(&b, a->table[i].k, a->table[i].v,1,1,0); \ + free(a->table); \ + a->table = b.table; \ + a->mask = b.mask; \ + a->count = b.count; \ + a->limit = b.limit; \ + a->deleted = b.deleted; \ + a->delete_threshhold = b.delete_threshhold; \ + a->grow_threshhold = b.grow_threshhold; \ + a->shrink_threshhold = b.shrink_threshhold; \ +} + +#define STB_equal(a,b) ((a) == (b)) + +#define stb_define_hash(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE) \ + stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \ + KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \ + STB_equal,STB_equal,HASH, \ + VALUE,STB_nonullvalue,0) + +#define stb_define_hash_vnull(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE,VNULL) \ + stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \ + KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \ + STB_equal,STB_equal,HASH, \ + VALUE,STB_nullvalue,VNULL) + +////////////////////////////////////////////////////////////////////////////// +// +// stb_ptrmap +// +// An stb_ptrmap data structure is an O(1) hash table between pointers. One +// application is to let you store "extra" data associated with pointers, +// which is why it was originally called stb_extra. + +#ifndef STB_INCLUDE_STB_LIB_H +stb_declare_hash(STB_EXTERN, stb_ptrmap, stb_ptrmap_, void *, void *) +stb_declare_hash(STB_EXTERN, stb_idict, stb_idict_, stb_int32, stb_int32) + +STB_EXTERN void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *)); +STB_EXTERN stb_ptrmap *stb_ptrmap_new(void); + +STB_EXTERN stb_idict * stb_idict_new_size(unsigned int size); +STB_EXTERN void stb_idict_remove_all(stb_idict *e); +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION + +#define STB_EMPTY ((void *) 2) +#define STB_EDEL ((void *) 6) + +stb_define_hash_base(STB_noprefix,stb_ptrmap, STB_nofields, stb_ptrmap_,stb_ptrmap_,0.85f, + void *,STB_EMPTY,STB_EDEL,STB_nocopy,STB_nodelete,STB_nosafe, + STB_equal,STB_equal,return stb_hashptr(k);, + void *,STB_nullvalue,NULL) + +stb_ptrmap *stb_ptrmap_new(void) +{ + return stb_ptrmap_create(); +} + +void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *)) +{ + int i; + if (free_func) + for (i=0; i < e->limit; ++i) + if (e->table[i].k != STB_EMPTY && e->table[i].k != STB_EDEL) { + if (free_func == free) + free(e->table[i].v); // allow STB_MALLOC_WRAPPER to operate + else + free_func(e->table[i].v); + } + stb_ptrmap_destroy(e); +} + +// extra fields needed for stua_dict +#define STB_IEMPTY ((int) 1) +#define STB_IDEL ((int) 3) +stb_define_hash_base(STB_noprefix, stb_idict, STB_nofields, stb_idict_,stb_idict_,0.85f, + stb_int32,STB_IEMPTY,STB_IDEL,STB_nocopy,STB_nodelete,STB_nosafe, + STB_equal,STB_equal, + return stb_rehash_improved(k);,stb_int32,STB_nonullvalue,0) + +stb_idict * stb_idict_new_size(unsigned int size) +{ + stb_idict *e = (stb_idict *) malloc(sizeof(*e)); + if (e) { + // round up to power of 2 + while ((size & (size-1)) != 0) // while more than 1 bit is set + size += (size & ~(size-1)); // add the lowest set bit + stb_idict_init(e, size); + e->alloced = 1; + } + return e; +} + +void stb_idict_remove_all(stb_idict *e) +{ + int n; + for (n=0; n < e->limit; ++n) + e->table[n].k = STB_IEMPTY; + e->has_empty = e->has_del = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// SDICT: Hash Table for Strings (symbol table) +// +// if "use_arena=1", then strings will be copied +// into blocks and never freed until the sdict is freed; +// otherwise they're malloc()ed and free()d on the fly. +// (specify use_arena=1 if you never stb_sdict_remove) + +#ifndef STB_INCLUDE_STB_LIB_H +stb_declare_hash(STB_EXTERN, stb_sdict, stb_sdict_, char *, void *) + +STB_EXTERN stb_sdict * stb_sdict_new(void); +STB_EXTERN stb_sdict * stb_sdict_copy(stb_sdict*); +STB_EXTERN void stb_sdict_delete(stb_sdict *); +STB_EXTERN void * stb_sdict_change(stb_sdict *, char *str, void *p); +STB_EXTERN int stb_sdict_count(stb_sdict *d); + +STB_EXTERN int stb_sdict_internal_limit(stb_sdict *d); +STB_EXTERN char * stb_sdict_internal_key(stb_sdict *d, int n); +STB_EXTERN void * stb_sdict_internal_value(stb_sdict *d, int n); + +#define stb_sdict_for(d,i,q,z) \ + for(i=0; i < stb_sdict_internal_limit(d) ? (q=stb_sdict_internal_key(d,i),z=stb_sdict_internal_value(d,i),1) : 0; ++i) \ + if (q==NULL||q==(void *) 1);else // reversed makes macro friendly +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION + +// if in same translation unit, for speed, don't call accessors +#undef stb_sdict_for +#define stb_sdict_for(d,i,q,z) \ + for(i=0; i < (d)->limit ? (q=(d)->table[i].k,z=(d)->table[i].v,1) : 0; ++i) \ + if (q==NULL||q==(void *) 1);else // reversed makes macro friendly + +//#define STB_DEL ((void *) 1) +#define STB_SDEL ((char *) 1) + +stb_define_hash_base(STB_noprefix, stb_sdict, STB_nofields, stb_sdict_,stb_sdictinternal_, 0.85f, + char *, NULL, STB_SDEL, strdup, free, + STB_safecompare, !strcmp, STB_equal, return stb_hash(k);, + void *, STB_nullvalue, NULL) + +int stb_sdict_count(stb_sdict *a) +{ + return a->count; +} + +int stb_sdict_internal_limit(stb_sdict *a) +{ + return a->limit; +} +char* stb_sdict_internal_key(stb_sdict *a, int n) +{ + return a->table[n].k; +} +void* stb_sdict_internal_value(stb_sdict *a, int n) +{ + return a->table[n].v; +} + +stb_sdict * stb_sdict_new(void) +{ + stb_sdict *d = stb_sdict_create(); + if (d == NULL) return NULL; + return d; +} + +stb_sdict* stb_sdict_copy(stb_sdict *old) +{ + return stb_sdictinternal_copy(old); +} + +void stb_sdict_delete(stb_sdict *d) +{ + stb_sdict_destroy(d); +} + +void * stb_sdict_change(stb_sdict *d, char *str, void *p) +{ + void *q = stb_sdict_get(d, str); + stb_sdict_set(d, str, p); + return q; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// File Processing +// + +#ifndef STB_INCLUDE_STB_LIB_H +#ifdef _MSC_VER + #define stb_rename(x,y) _wrename((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y)) + #define stb_mktemp _mktemp +#else + #define stb_mktemp mktemp + #define stb_rename rename +#endif + +#define stb_filec (char *) stb_file +#define stb_fileu (unsigned char *) stb_file +STB_EXTERN void * stb_file(char *filename, size_t *length); +STB_EXTERN size_t stb_filelen(FILE *f); +STB_EXTERN int stb_filewrite(char *filename, void *data, size_t length); +STB_EXTERN int stb_filewritestr(char *filename, char *data); +STB_EXTERN char ** stb_stringfile(char *filename, int *len); +STB_EXTERN char * stb_fgets(char *buffer, int buflen, FILE *f); +STB_EXTERN char * stb_fgets_malloc(FILE *f); +STB_EXTERN int stb_fexists(char *filename); +STB_EXTERN int stb_fcmp(char *s1, char *s2); +STB_EXTERN int stb_feq(char *s1, char *s2); +STB_EXTERN time_t stb_ftimestamp(char *filename); +STB_EXTERN int stb_fullpath(char *abs, int abs_size, char *rel); + +STB_EXTERN int stb_copyfile(char *src, char *dest); +STB_EXTERN int stb_fread(void *data, size_t len, size_t count, void *f); +STB_EXTERN int stb_fwrite(void *data, size_t len, size_t count, void *f); +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION +#if defined(_MSC_VER) || defined(__MINGW32__) + #define stb__stat _stat +#else + #define stb__stat stat +#endif + +int stb_fexists(char *filename) +{ + struct stb__stat buf; + return stb__windows( + _wstat((const wchar_t *)stb__from_utf8(filename), &buf), + stat(filename,&buf) + ) == 0; +} + +time_t stb_ftimestamp(char *filename) +{ + struct stb__stat buf; + if (stb__windows( + _wstat((const wchar_t *)stb__from_utf8(filename), &buf), + stat(filename,&buf) + ) == 0) + { + return buf.st_mtime; + } else { + return 0; + } +} + +size_t stb_filelen(FILE *f) +{ + size_t len, pos; + pos = ftell(f); + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, pos, SEEK_SET); + return len; +} + +void *stb_file(char *filename, size_t *length) +{ + FILE *f = stb__fopen(filename, "rb"); + char *buffer; + size_t len, len2; + if (!f) return NULL; + len = stb_filelen(f); + buffer = (char *) malloc(len+2); // nul + extra + len2 = fread(buffer, 1, len, f); + if (len2 == len) { + if (length) *length = len; + buffer[len] = 0; + } else { + free(buffer); + buffer = NULL; + } + fclose(f); + return buffer; +} + +int stb_filewrite(char *filename, void *data, size_t length) +{ + FILE *f = stb__fopen(filename, "wb"); + if (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; + } + fclose(f); + } + return f != NULL; +} + +int stb_filewritestr(char *filename, char *data) +{ + return stb_filewrite(filename, data, strlen(data)); +} + +char ** stb_stringfile(char *filename, int *plen) +{ + FILE *f = stb__fopen(filename, "rb"); + char *buffer, **list=NULL, *s; + size_t len, count, i; + + if (!f) return NULL; + len = stb_filelen(f); + buffer = (char *) malloc(len+1); + len = fread(buffer, 1, len, f); + buffer[len] = 0; + fclose(f); + + // two passes through: first time count lines, second time set them + for (i=0; i < 2; ++i) { + s = buffer; + if (i == 1) + list[0] = s; + count = 1; + while (*s) { + if (*s == '\n' || *s == '\r') { + // detect if both cr & lf are together + int crlf = (s[0] + s[1]) == ('\n' + '\r'); + if (i == 1) *s = 0; + if (crlf) ++s; + if (s[1]) { // it's not over yet + if (i == 1) list[count] = s+1; + ++count; + } + } + ++s; + } + if (i == 0) { + list = (char **) malloc(sizeof(*list) * (count+1) + len+1); + if (!list) return NULL; + list[count] = 0; + // recopy the file so there's just a single allocation to free + memcpy(&list[count+1], buffer, len+1); + free(buffer); + buffer = (char *) &list[count+1]; + if (plen) *plen = count; + } + } + return list; +} + +char * stb_fgets(char *buffer, int buflen, FILE *f) +{ + char *p; + buffer[0] = 0; + p = fgets(buffer, buflen, f); + if (p) { + int n = strlen(p)-1; + if (n >= 0) + if (p[n] == '\n') + p[n] = 0; + } + return p; +} + +char * stb_fgets_malloc(FILE *f) +{ + // avoid reallocing for small strings + char quick_buffer[800]; + quick_buffer[sizeof(quick_buffer)-2] = 0; + if (!fgets(quick_buffer, sizeof(quick_buffer), f)) + return NULL; + + if (quick_buffer[sizeof(quick_buffer)-2] == 0) { + int n = strlen(quick_buffer); + if (n > 0 && quick_buffer[n-1] == '\n') + quick_buffer[n-1] = 0; + return strdup(quick_buffer); + } else { + char *p; + char *a = strdup(quick_buffer); + int len = sizeof(quick_buffer)-1; + + while (!feof(f)) { + if (a[len-1] == '\n') break; + a = (char *) realloc(a, len*2); + p = &a[len]; + p[len-2] = 0; + if (!fgets(p, len, f)) + break; + if (p[len-2] == 0) { + len += strlen(p); + break; + } + len = len + (len-1); + } + if (a[len-1] == '\n') + a[len-1] = 0; + return a; + } +} + +int stb_fullpath(char *abs, int abs_size, char *rel) +{ + #ifdef _MSC_VER + return _fullpath(abs, rel, abs_size) != NULL; + #else + if (rel[0] == '/' || rel[0] == '~') { + if ((int) strlen(rel) >= abs_size) + return 0; + strcpy(abs,rel); + return 1; + } else { + int n; + getcwd(abs, abs_size); + n = strlen(abs); + if (n+(int) strlen(rel)+2 <= abs_size) { + abs[n] = '/'; + strcpy(abs+n+1, rel); + return 1; + } else { + return 0; + } + } + #endif +} + +static int stb_fcmp_core(FILE *f, FILE *g) +{ + char buf1[1024],buf2[1024]; + int n1,n2, res=0; + + while (1) { + n1 = fread(buf1, 1, sizeof(buf1), f); + n2 = fread(buf2, 1, sizeof(buf2), g); + res = memcmp(buf1,buf2,n1 < n2 ? n1 : n2); + if (res) + break; + if (n1 != n2) { + res = n1 < n2 ? -1 : 1; + break; + } + if (n1 == 0) + break; + } + + fclose(f); + fclose(g); + return res; +} + +int stb_fcmp(char *s1, char *s2) +{ + FILE *f = stb__fopen(s1, "rb"); + FILE *g = stb__fopen(s2, "rb"); + + if (f == NULL || g == NULL) { + if (f) fclose(f); + if (g) { + fclose(g); + return 1; + } + return f != NULL; + } + + return stb_fcmp_core(f,g); +} + +int stb_feq(char *s1, char *s2) +{ + FILE *f = stb__fopen(s1, "rb"); + FILE *g = stb__fopen(s2, "rb"); + + if (f == NULL || g == NULL) { + if (f) fclose(f); + if (g) fclose(g); + return f == g; + } + + // feq is faster because it shortcuts if they're different length + if (stb_filelen(f) != stb_filelen(g)) { + fclose(f); + fclose(g); + return 0; + } + + return !stb_fcmp_core(f,g); +} + +int stb_copyfile(char *src, char *dest) +{ + char raw_buffer[1024]; + char *buffer; + int buf_size = 65536; + + FILE *f, *g; + + // if file already exists at destination, do nothing + if (stb_feq(src, dest)) return 1; + + // open file + f = stb__fopen(src, "rb"); + if (f == NULL) return 0; + + // open file for writing + g = stb__fopen(dest, "wb"); + if (g == NULL) { + fclose(f); + return 0; + } + + buffer = (char *) malloc(buf_size); + if (buffer == NULL) { + buffer = raw_buffer; + buf_size = sizeof(raw_buffer); + } + + while (!feof(f)) { + int n = fread(buffer, 1, buf_size, f); + if (n != 0) + fwrite(buffer, 1, n, g); + } + + fclose(f); + if (buffer != raw_buffer) + free(buffer); + + fclose(g); + return 1; +} + +#define stb_fgetc(f) ((unsigned char) fgetc(f)) + +#if 0 +// strip the trailing '/' or '\\' from a directory so we can refer to it +// as a file for _stat() +char *stb_strip_final_slash(char *t) +{ + if (t[0]) { + char *z = t + strlen(t) - 1; + // *z is the last character + if (*z == '\\' || *z == '/') + if (z != t+2 || t[1] != ':') // but don't strip it if it's e.g. "c:/" + *z = 0; + if (*z == '\\') + *z = '/'; // canonicalize to make sure it matches db + } + 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 +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Portable directory reading +// + +#ifndef STB_INCLUDE_STB_LIB_H +STB_EXTERN char **stb_readdir_files (char *dir); +STB_EXTERN char **stb_readdir_files_mask(char *dir, char *wild); +STB_EXTERN char **stb_readdir_subdirs(char *dir); +STB_EXTERN char **stb_readdir_subdirs_mask(char *dir, char *wild); +STB_EXTERN void stb_readdir_free (char **files); +STB_EXTERN char **stb_readdir_recursive(char *dir, char *filespec); +STB_EXTERN void stb_delete_directory_recursive(char *dir); + +// forward declare for implementation +STB_EXTERN int stb_wildmatchi(char *expr, char *candidate); +#endif // STB_INCLUDE_STB_LIB_H + + +#ifdef STB_LIB_IMPLEMENTATION + +#ifdef _MSC_VER +#include +#else +#include +#include +#endif + +void stb_readdir_free(char **files) +{ + char **f2 = files; + int i; + for (i=0; i < stb_arr_len(f2); ++i) + free(f2[i]); + stb_arr_free(f2); +} + +static int isdotdirname(char *name) +{ + if (name[0] == '.') + return (name[1] == '.') ? !name[2] : !name[1]; + return 0; +} + +static char **readdir_raw(char *dir, int return_subdirs, char *mask) +{ + char **results = NULL; + char buffer[4096], with_slash[4096]; + 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; + #endif + #else // !_MSC_VER + const DIR *none = NULL; + DIR *z; + #endif + + n = stb_strscpy(buffer,dir,sizeof(buffer)); + if (!n || n >= sizeof(buffer)) + return NULL; + stb_fixpath(buffer); + n--; + + if (n > 0 && (buffer[n-1] != '/')) { + buffer[n++] = '/'; + } + buffer[n] = 0; + if (!stb_strscpy(with_slash,buffer,sizeof(with_slash))) + return NULL; + + #ifdef _MSC_VER + 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 = 1; + #ifndef _MSC_VER + struct dirent *data = readdir(z); + nonempty = (data != NULL); + #endif + + if (nonempty) { + + do { + int is_subdir; + #ifdef _MSC_VER + char *name = stb__to_utf8((stb__wchar *)data.name); + if (name == NULL) { + fprintf(stderr, "%s to convert '%S' to %s!\n", "Unable", data.name, "utf8"); + continue; + } + is_subdir = !!(data.attrib & _A_SUBDIR); + #else + char *name = data->d_name; + 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[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)); + } + } + } + } + #ifdef _MSC_VER + while (0 == _wfindnext(z, &data)); + #else + while ((data = readdir(z)) != NULL); + #endif + } + #ifdef _MSC_VER + _findclose(z); + #else + closedir(z); + #endif + } + return results; +} + +char **stb_readdir_files (char *dir) { return readdir_raw(dir, 0, NULL); } +char **stb_readdir_subdirs(char *dir) { return readdir_raw(dir, 1, NULL); } +char **stb_readdir_files_mask(char *dir, char *wild) { return readdir_raw(dir, 0, wild); } +char **stb_readdir_subdirs_mask(char *dir, char *wild) { return readdir_raw(dir, 1, wild); } + +int stb__rec_max=0x7fffffff; +static char **stb_readdir_rec(char **sofar, char *dir, char *filespec) +{ + char **files; + char ** dirs; + char **p; + + if (stb_arr_len(sofar) >= stb__rec_max) return sofar; + + files = stb_readdir_files_mask(dir, filespec); + stb_arr_for(p, files) { + stb_arr_push(sofar, strdup(*p)); + if (stb_arr_len(sofar) >= stb__rec_max) break; + } + stb_readdir_free(files); + if (stb_arr_len(sofar) >= stb__rec_max) return sofar; + + dirs = stb_readdir_subdirs(dir); + stb_arr_for(p, dirs) + sofar = stb_readdir_rec(sofar, *p, filespec); + stb_readdir_free(dirs); + return sofar; +} + +char **stb_readdir_recursive(char *dir, char *filespec) +{ + return stb_readdir_rec(NULL, dir, filespec); +} + +void stb_delete_directory_recursive(char *dir) +{ + char **list = stb_readdir_subdirs(dir); + int i; + for (i=0; i < stb_arr_len(list); ++i) + stb_delete_directory_recursive(list[i]); + stb_arr_free(list); + list = stb_readdir_files(dir); + for (i=0; i < stb_arr_len(list); ++i) + if (!remove(list[i])) { + // on windows, try again after making it writeable; don't ALWAYS + // do this first since that would be slow in the normal case + #ifdef _MSC_VER + _chmod(list[i], _S_IWRITE); + remove(list[i]); + #endif + } + stb_arr_free(list); + stb__windows(_rmdir,rmdir)(dir); +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Checksums: CRC-32, ADLER32, SHA-1 +// +// CRC-32 and ADLER32 allow streaming blocks +// SHA-1 requires either a complete buffer, max size 2^32 - 73 +// or it can checksum directly from a file, max 2^61 + +#ifndef STB_INCLUDE_STB_LIB_H +#define STB_ADLER32_SEED 1 +#define STB_CRC32_SEED 0 // note that we logical NOT this in the code + +STB_EXTERN stb_uint stb_adler32 (stb_uint adler32, stb_uchar *buffer, stb_uint buflen); +STB_EXTERN stb_uint stb_crc32_block(stb_uint crc32 , stb_uchar *buffer, stb_uint buflen); +STB_EXTERN stb_uint stb_crc32 ( stb_uchar *buffer, stb_uint buflen); + +STB_EXTERN void stb_sha1( unsigned char output[20], stb_uchar *buffer, unsigned int len); +STB_EXTERN int stb_sha1_file(unsigned char output[20], char *file); +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION +stb_uint stb_crc32_block(stb_uint crc, unsigned char *buffer, stb_uint len) +{ + static stb_uint crc_table[256]; + stb_uint i,j,s; + crc = ~crc; + + if (crc_table[1] == 0) + for(i=0; i < 256; i++) { + for (s=i, j=0; j < 8; ++j) + s = (s >> 1) ^ (s & 1 ? 0xedb88320 : 0); + crc_table[i] = s; + } + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +stb_uint stb_crc32(unsigned char *buffer, stb_uint len) +{ + return stb_crc32_block(0, buffer, len); +} + +stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen) +{ + const unsigned long ADLER_MOD = 65521; + unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; + unsigned long blocklen, i; + + blocklen = buflen % 5552; + while (buflen) { + for (i=0; i + 7 < blocklen; i += 8) { + s1 += buffer[0], s2 += s1; + s1 += buffer[1], s2 += s1; + s1 += buffer[2], s2 += s1; + s1 += buffer[3], s2 += s1; + s1 += buffer[4], s2 += s1; + s1 += buffer[5], s2 += s1; + s1 += buffer[6], s2 += s1; + s1 += buffer[7], s2 += s1; + + buffer += 8; + } + + for (; i < blocklen; ++i) + s1 += *buffer++, s2 += s1; + + s1 %= ADLER_MOD, s2 %= ADLER_MOD; + buflen -= blocklen; + blocklen = 5552; + } + return (s2 << 16) + s1; +} + +#define stb__big32(c) (((c)[0]<<24) + (c)[1]*65536 + (c)[2]*256 + (c)[3]) +static void stb__sha1(stb_uchar *chunk, stb_uint h[5]) +{ + int i; + stb_uint a,b,c,d,e; + stb_uint w[80]; + + for (i=0; i < 16; ++i) + w[i] = stb__big32(&chunk[i*4]); + for (i=16; i < 80; ++i) { + stb_uint t; + t = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]; + w[i] = (t + t) | (t >> 31); + } + + a = h[0]; + b = h[1]; + c = h[2]; + d = h[3]; + e = h[4]; + + #define STB__SHA1(k,f) \ + { \ + stb_uint temp = (a << 5) + (a >> 27) + (f) + e + (k) + w[i]; \ + e = d; \ + d = c; \ + c = (b << 30) + (b >> 2); \ + b = a; \ + a = temp; \ + } + + i=0; + for (; i < 20; ++i) STB__SHA1(0x5a827999, d ^ (b & (c ^ d)) ); + for (; i < 40; ++i) STB__SHA1(0x6ed9eba1, b ^ c ^ d ); + for (; i < 60; ++i) STB__SHA1(0x8f1bbcdc, (b & c) + (d & (b ^ c)) ); + for (; i < 80; ++i) STB__SHA1(0xca62c1d6, b ^ c ^ d ); + + #undef STB__SHA1 + + h[0] += a; + h[1] += b; + h[2] += c; + h[3] += d; + h[4] += e; +} + +void stb_sha1(stb_uchar output[20], stb_uchar *buffer, stb_uint len) +{ + unsigned char final_block[128]; + stb_uint end_start, final_len, j; + int i; + + stb_uint h[5]; + + h[0] = 0x67452301; + h[1] = 0xefcdab89; + h[2] = 0x98badcfe; + h[3] = 0x10325476; + h[4] = 0xc3d2e1f0; + + // we need to write padding to the last one or two + // blocks, so build those first into 'final_block' + + // we have to write one special byte, plus the 8-byte length + + // compute the block where the data runs out + end_start = len & ~63; + + // compute the earliest we can encode the length + if (((len+9) & ~63) == end_start) { + // it all fits in one block, so fill a second-to-last block + end_start -= 64; + } + + final_len = end_start + 128; + + // now we need to copy the data in + assert(end_start + 128 >= len+9); + assert(end_start < len || len < 64-9); + + j = 0; + if (end_start > len) + j = (stb_uint) - (int) end_start; + + for (; end_start + j < len; ++j) + final_block[j] = buffer[end_start + j]; + final_block[j++] = 0x80; + while (j < 128-5) // 5 byte length, so write 4 extra padding bytes + final_block[j++] = 0; + // big-endian size + final_block[j++] = len >> 29; + final_block[j++] = len >> 21; + final_block[j++] = len >> 13; + final_block[j++] = len >> 5; + final_block[j++] = len << 3; + assert(j == 128 && end_start + j == final_len); + + for (j=0; j < final_len; j += 64) { // 512-bit chunks + if (j+64 >= end_start+64) + stb__sha1(&final_block[j - end_start], h); + else + stb__sha1(&buffer[j], h); + } + + for (i=0; i < 5; ++i) { + output[i*4 + 0] = h[i] >> 24; + output[i*4 + 1] = h[i] >> 16; + output[i*4 + 2] = h[i] >> 8; + output[i*4 + 3] = h[i] >> 0; + } +} + +int stb_sha1_file(stb_uchar output[20], char *file) +{ + int i; + stb_uint64 length=0; + unsigned char buffer[128]; + + FILE *f = stb__fopen(file, "rb"); + stb_uint h[5]; + + if (f == NULL) return 0; // file not found + + h[0] = 0x67452301; + h[1] = 0xefcdab89; + h[2] = 0x98badcfe; + h[3] = 0x10325476; + h[4] = 0xc3d2e1f0; + + for(;;) { + int n = fread(buffer, 1, 64, f); + if (n == 64) { + stb__sha1(buffer, h); + length += n; + } else { + int block = 64; + + length += n; + + buffer[n++] = 0x80; + + // if there isn't enough room for the length, double the block + if (n + 8 > 64) + block = 128; + + // pad to end + memset(buffer+n, 0, block-8-n); + + i = block - 8; + buffer[i++] = (stb_uchar) (length >> 53); + buffer[i++] = (stb_uchar) (length >> 45); + buffer[i++] = (stb_uchar) (length >> 37); + buffer[i++] = (stb_uchar) (length >> 29); + buffer[i++] = (stb_uchar) (length >> 21); + buffer[i++] = (stb_uchar) (length >> 13); + buffer[i++] = (stb_uchar) (length >> 5); + buffer[i++] = (stb_uchar) (length << 3); + assert(i == block); + stb__sha1(buffer, h); + if (block == 128) + stb__sha1(buffer+64, h); + else + assert(block == 64); + break; + } + } + fclose(f); + + for (i=0; i < 5; ++i) { + output[i*4 + 0] = h[i] >> 24; + output[i*4 + 1] = h[i] >> 16; + output[i*4 + 2] = h[i] >> 8; + output[i*4 + 3] = h[i] >> 0; + } + + return 1; +} +#endif // STB_LIB_IMPLEMENTATION + +////////////////////////////////////////////////////////////////////////////// +// +// Random Numbers via Meresenne Twister or LCG +// + +#ifndef STB_INCLUDE_STB_LIB_H +STB_EXTERN unsigned long stb_srandLCG(unsigned long seed); +STB_EXTERN unsigned long stb_randLCG(void); +STB_EXTERN double stb_frandLCG(void); + +STB_EXTERN void stb_srand(unsigned long seed); +STB_EXTERN unsigned long stb_rand(void); +STB_EXTERN double stb_frand(void); +STB_EXTERN void stb_shuffle(void *p, size_t n, size_t sz, + unsigned long seed); +STB_EXTERN void stb_reverse(void *p, size_t n, size_t sz); + +STB_EXTERN unsigned long stb_randLCG_explicit(unsigned long seed); +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION +unsigned long stb_randLCG_explicit(unsigned long seed) +{ + return seed * 2147001325 + 715136305; +} + +static unsigned long stb__rand_seed=0; + +unsigned long stb_srandLCG(unsigned long seed) +{ + unsigned long previous = stb__rand_seed; + stb__rand_seed = seed; + return previous; +} + +unsigned long stb_randLCG(void) +{ + stb__rand_seed = stb__rand_seed * 2147001325 + 715136305; // BCPL generator + // shuffle non-random bits to the middle, and xor to decorrelate with seed + return 0x31415926 ^ ((stb__rand_seed >> 16) + (stb__rand_seed << 16)); +} + +double stb_frandLCG(void) +{ + return stb_randLCG() / ((double) (1 << 16) * (1 << 16)); +} + +void stb_shuffle(void *p, size_t n, size_t sz, unsigned long seed) +{ + char *a; + unsigned long old_seed; + int i; + if (seed) + old_seed = stb_srandLCG(seed); + a = (char *) p + (n-1) * sz; + + for (i=n; i > 1; --i) { + int j = stb_randLCG() % i; + stb_swap(a, (char *) p + j * sz, sz); + a -= sz; + } + if (seed) + stb_srandLCG(old_seed); +} + +void stb_reverse(void *p, size_t n, size_t sz) +{ + int i,j = n-1; + for (i=0; i < j; ++i,--j) { + stb_swap((char *) p + i * sz, (char *) p + j * sz, sz); + } +} + +// public domain Mersenne Twister by Michael Brundage +#define STB__MT_LEN 624 + +int stb__mt_index = STB__MT_LEN*sizeof(unsigned long)+1; +unsigned long stb__mt_buffer[STB__MT_LEN]; + +void stb_srand(unsigned long seed) +{ + int i; + unsigned long old = stb_srandLCG(seed); + for (i = 0; i < STB__MT_LEN; i++) + stb__mt_buffer[i] = stb_randLCG(); + stb_srandLCG(old); + stb__mt_index = STB__MT_LEN*sizeof(unsigned long); +} + +#define STB__MT_IA 397 +#define STB__MT_IB (STB__MT_LEN - STB__MT_IA) +#define STB__UPPER_MASK 0x80000000 +#define STB__LOWER_MASK 0x7FFFFFFF +#define STB__MATRIX_A 0x9908B0DF +#define STB__TWIST(b,i,j) ((b)[i] & STB__UPPER_MASK) | ((b)[j] & STB__LOWER_MASK) +#define STB__MAGIC(s) (((s)&1)*STB__MATRIX_A) + +unsigned long stb_rand() +{ + unsigned long * b = stb__mt_buffer; + int idx = stb__mt_index; + unsigned long s,r; + int i; + + if (idx >= STB__MT_LEN*sizeof(unsigned long)) { + if (idx > STB__MT_LEN*sizeof(unsigned long)) + stb_srand(0); + idx = 0; + i = 0; + for (; i < STB__MT_IB; i++) { + s = STB__TWIST(b, i, i+1); + b[i] = b[i + STB__MT_IA] ^ (s >> 1) ^ STB__MAGIC(s); + } + for (; i < STB__MT_LEN-1; i++) { + s = STB__TWIST(b, i, i+1); + b[i] = b[i - STB__MT_IB] ^ (s >> 1) ^ STB__MAGIC(s); + } + + s = STB__TWIST(b, STB__MT_LEN-1, 0); + b[STB__MT_LEN-1] = b[STB__MT_IA-1] ^ (s >> 1) ^ STB__MAGIC(s); + } + stb__mt_index = idx + sizeof(unsigned long); + + r = *(unsigned long *)((unsigned char *)b + idx); + + r ^= (r >> 11); + r ^= (r << 7) & 0x9D2C5680; + r ^= (r << 15) & 0xEFC60000; + r ^= (r >> 18); + + return r; +} + +double stb_frand(void) +{ + return stb_rand() / ((double) (1 << 16) * (1 << 16)); +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// wildcards and regexping +// + +#ifndef STB_INCLUDE_STB_LIB_H +STB_EXTERN int stb_wildmatch (char *expr, char *candidate); +STB_EXTERN int stb_wildmatchi(char *expr, char *candidate); +STB_EXTERN int stb_wildfind (char *expr, char *candidate); +STB_EXTERN int stb_wildfindi (char *expr, char *candidate); +#endif // STB_INCLUDE_STB_LIB_H + +#ifdef STB_LIB_IMPLEMENTATION +static int stb__match_qstring(char *candidate, char *qstring, int qlen, int insensitive) +{ + int i; + if (insensitive) { + for (i=0; i < qlen; ++i) + if (qstring[i] == '?') { + if (!candidate[i]) return 0; + } else + if (tolower(qstring[i]) != tolower(candidate[i])) + return 0; + } else { + for (i=0; i < qlen; ++i) + if (qstring[i] == '?') { + if (!candidate[i]) return 0; + } else + if (qstring[i] != candidate[i]) + return 0; + } + return 1; +} + +static int stb__find_qstring(char *candidate, char *qstring, int qlen, int insensitive) +{ + char c; + + int offset=0; + while (*qstring == '?') { + ++qstring; + --qlen; + ++candidate; + if (qlen == 0) return 0; + if (*candidate == 0) return -1; + } + + c = *qstring++; + --qlen; + if (insensitive) c = tolower(c); + + while (candidate[offset]) { + if (c == (insensitive ? tolower(candidate[offset]) : candidate[offset])) + if (stb__match_qstring(candidate+offset+1, qstring, qlen, insensitive)) + return offset; + ++offset; + } + + return -1; +} + +int stb__wildmatch_raw2(char *expr, char *candidate, int search, int insensitive) +{ + int where=0; + int start = -1; + + if (!search) { + // parse to first '*' + if (*expr != '*') + start = 0; + while (*expr != '*') { + if (!*expr) + return *candidate == 0 ? 0 : -1; + if (*expr == '?') { + if (!*candidate) return -1; + } else { + if (insensitive) { + if (tolower(*candidate) != tolower(*expr)) + return -1; + } else + if (*candidate != *expr) + return -1; + } + ++candidate, ++expr, ++where; + } + } else { + // 0-length search string + if (!*expr) + return 0; + } + + assert(search || *expr == '*'); + if (!search) + ++expr; + + // implicit '*' at this point + + while (*expr) { + int o=0; + // combine redundant * characters + while (expr[0] == '*') ++expr; + + // ok, at this point, expr[-1] == '*', + // and expr[0] != '*' + + if (!expr[0]) return start >= 0 ? start : 0; + + // now find next '*' + o = 0; + while (expr[o] != '*') { + if (expr[o] == 0) + break; + ++o; + } + // if no '*', scan to end, then match at end + if (expr[o] == 0 && !search) { + int z; + for (z=0; z < o; ++z) + if (candidate[z] == 0) + return -1; + while (candidate[z]) + ++z; + // ok, now check if they match + if (stb__match_qstring(candidate+z-o, expr, o, insensitive)) + return start >= 0 ? start : 0; + return -1; + } else { + // if yes '*', then do stb__find_qmatch on the intervening chars + int n = stb__find_qstring(candidate, expr, o, insensitive); + if (n < 0) + return -1; + if (start < 0) + start = where + n; + expr += o; + candidate += n+o; + } + + if (*expr == 0) { + assert(search); + return start; + } + + assert(*expr == '*'); + ++expr; + } + + return start >= 0 ? start : 0; +} + +int stb__wildmatch_raw(char *expr, char *candidate, int search, int insensitive) +{ + char buffer[256]; + // handle multiple search strings + char *s = strchr(expr, ';'); + char *last = expr; + while (s) { + int z; + // need to allow for non-writeable strings... assume they're small + if (s - last < 256) { + stb_strncpy(buffer, last, s-last+1); + z = stb__wildmatch_raw2(buffer, candidate, search, insensitive); + } else { + *s = 0; + z = stb__wildmatch_raw2(last, candidate, search, insensitive); + *s = ';'; + } + if (z >= 0) return z; + last = s+1; + s = strchr(last, ';'); + } + return stb__wildmatch_raw2(last, candidate, search, insensitive); +} + +int stb_wildmatch(char *expr, char *candidate) +{ + return stb__wildmatch_raw(expr, candidate, 0,0) >= 0; +} + +int stb_wildmatchi(char *expr, char *candidate) +{ + return stb__wildmatch_raw(expr, candidate, 0,1) >= 0; +} + +int stb_wildfind(char *expr, char *candidate) +{ + return stb__wildmatch_raw(expr, candidate, 1,0); +} + +int stb_wildfindi(char *expr, char *candidate) +{ + return stb__wildmatch_raw(expr, candidate, 1,1); +} + +#undef STB_LIB_IMPLEMENTATION +#endif // STB_LIB_IMPLEMENTATION + +#ifndef STB_INCLUDE_STB_LIB_H +#define STB_INCLUDE_STB_LIB_H +#undef STB_EXTERN +#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/tests/stb.dsw b/tests/stb.dsw index 45a52b6..ef3c43e 100644 --- a/tests/stb.dsw +++ b/tests/stb.dsw @@ -123,6 +123,18 @@ Package=<4> ############################################################################### +Project: "stblib"=.\stblib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Project: "stretch_test"=.\stretch_test.dsp - Package Owner=<4> Package=<5> diff --git a/tests/stblib.dsp b/tests/stblib.dsp new file mode 100644 index 0000000..f0ede02 --- /dev/null +++ b/tests/stblib.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="stblib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=stblib - 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 "stblib.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 "stblib.mak" CFG="stblib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "stblib - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "stblib - 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)" == "stblib - 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 /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 +# 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)" == "stblib - 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 /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 +# 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 "stblib - Win32 Release" +# Name "stblib - Win32 Debug" +# Begin Source File + +SOURCE=..\stb_lib.h +# End Source File +# Begin Source File + +SOURCE=..\stb_regex.h +# End Source File +# Begin Source File + +SOURCE=.\stblib_test.c +# End Source File +# Begin Source File + +SOURCE=.\stblib_test_companion.c +# End Source File +# End Target +# End Project diff --git a/tests/stblib_test.c b/tests/stblib_test.c new file mode 100644 index 0000000..af110d2 --- /dev/null +++ b/tests/stblib_test.c @@ -0,0 +1,11 @@ +#include "stb_lib.h" +#define STB_LIB_IMPLEMENTATION +#include "stb_lib.h" + +//#define STB_REGEX_IMPLEMENTATION +//#include "stb_regex.h" + +int main(int argc, char **argv) +{ + +} \ No newline at end of file diff --git a/tests/stblib_test_companion.c b/tests/stblib_test_companion.c new file mode 100644 index 0000000..e1f7e68 --- /dev/null +++ b/tests/stblib_test_companion.c @@ -0,0 +1,4 @@ +//#include "stb_regex.h" +//#include "stb_regex.h" +#include "stb_lib.h" +#include "stb_lib.h" From ccee11ad79f08f85af9444659529b8ba4c6d51d1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:28:37 -0800 Subject: [PATCH 74/99] stb_image: fix warnings --- stb_image.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index 50286af..ee21554 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.17b - public domain image loader - http://nothings.org/stb +/* stb_image - v2.18 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: @@ -48,6 +48,7 @@ LICENSE RECENT REVISION HISTORY: + 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC @@ -1330,10 +1331,11 @@ STBIDEF int stbi_is_hdr (char const *filename) return result; } -STBIDEF int stbi_is_hdr_from_file(FILE *f) +STBIDEF int stbi_is_hdr_from_file(FILE *f) { #ifndef STBI_NO_HDR - long pos = ftell(f), res; + long pos = ftell(f); + int res; stbi__context s; stbi__start_file(&s,f); res = stbi__hdr_test(&s); @@ -2213,7 +2215,7 @@ static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) // (1|2|3|4|5|6|7)==0 0 seconds // all separate -0.047 seconds // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds - int dcterm = d[0] << 2; + int dcterm = d[0]*4; v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; } else { STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) From 01daa3a244d57b97993d2a9711943c09c0dc18af Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:29:31 -0800 Subject: [PATCH 75/99] stb_sprintf: fix size-only snprintf query --- stb_sprintf.h | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 225eda2..0ad26b2 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -1,4 +1,4 @@ -// stb_sprintf - v1.04 - public domain snprintf() implementation +// stb_sprintf - v1.05 - public domain snprintf() implementation // originally by Jeff Roberts / RAD Game Tools, 2015/10/20 // http://github.com/nothings/stb // @@ -14,6 +14,7 @@ // Jari Komppa (SI suffixes) // Rohit Nirmal // Marcin Wojdyr +// Leonard Ritter // // LICENSE: // @@ -1343,24 +1344,42 @@ static char *stbsp__clamp_callback(char *buf, void *user, int len) return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can } -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va) +static char * stbsp__count_clamp_callback( char * buf, void * user, int len ) +{ + stbsp__context * c = (stbsp__context*)user; + + c->count += len; + return c->tmp; // go direct into buffer if you can +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) { stbsp__context c; int l; - if (count == 0) - return 0; + if ( (count == 0) && !buf ) + { + c.count = 0; - c.buf = buf; - c.count = count; + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va ); + l = c.count; + } + else + { + if ( count == 0 ) + return 0; - STB_SPRINTF_DECORATE(vsprintfcb)(stbsp__clamp_callback, &c, stbsp__clamp_callback(0, &c, 0), fmt, va); + c.buf = buf; + c.count = count; - // 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; + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(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; } From 085ba4b627a13f259dcb84f856768f605e4ac0aa Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:31:18 -0800 Subject: [PATCH 76/99] add compilation tests that have no other includes to avoid accidental dependencies --- tests/test_c_lexer.c | 1 + tests/test_dxt.c | 1 + tests/test_easyfont.c | 1 + tests/test_image.c | 1 + tests/test_image_write.c | 1 + tests/test_perlin.c | 1 + tests/test_sprintf.c | 1 + tests/test_voxel.c | 1 + 8 files changed, 8 insertions(+) create mode 100644 tests/test_c_lexer.c create mode 100644 tests/test_dxt.c create mode 100644 tests/test_easyfont.c create mode 100644 tests/test_image.c create mode 100644 tests/test_image_write.c create mode 100644 tests/test_perlin.c create mode 100644 tests/test_sprintf.c create mode 100644 tests/test_voxel.c diff --git a/tests/test_c_lexer.c b/tests/test_c_lexer.c new file mode 100644 index 0000000..579ed5d --- /dev/null +++ b/tests/test_c_lexer.c @@ -0,0 +1 @@ +#include "stb_c_lexer.h" diff --git a/tests/test_dxt.c b/tests/test_dxt.c new file mode 100644 index 0000000..a1ef29d --- /dev/null +++ b/tests/test_dxt.c @@ -0,0 +1 @@ +#include "stb_dxt.h" diff --git a/tests/test_easyfont.c b/tests/test_easyfont.c new file mode 100644 index 0000000..70f284b --- /dev/null +++ b/tests/test_easyfont.c @@ -0,0 +1 @@ +#include "stb_easy_font.h" diff --git a/tests/test_image.c b/tests/test_image.c new file mode 100644 index 0000000..e23d4a0 --- /dev/null +++ b/tests/test_image.c @@ -0,0 +1 @@ +#include "stb_image.h" \ No newline at end of file diff --git a/tests/test_image_write.c b/tests/test_image_write.c new file mode 100644 index 0000000..cf23025 --- /dev/null +++ b/tests/test_image_write.c @@ -0,0 +1 @@ +#include "stb_image_write.h" \ No newline at end of file diff --git a/tests/test_perlin.c b/tests/test_perlin.c new file mode 100644 index 0000000..de702c9 --- /dev/null +++ b/tests/test_perlin.c @@ -0,0 +1 @@ +#include "stb_perlin.h" \ No newline at end of file diff --git a/tests/test_sprintf.c b/tests/test_sprintf.c new file mode 100644 index 0000000..078faa8 --- /dev/null +++ b/tests/test_sprintf.c @@ -0,0 +1 @@ +#include "stb_sprintf.h" \ No newline at end of file diff --git a/tests/test_voxel.c b/tests/test_voxel.c new file mode 100644 index 0000000..e177b6f --- /dev/null +++ b/tests/test_voxel.c @@ -0,0 +1 @@ +#include "stb_voxel_render.h" \ No newline at end of file From 602e986824b90c4bb17605f4976985c2f5601f08 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:39:29 -0800 Subject: [PATCH 77/99] fix STBI_NO_HDR and STBI_NO_LINEAR to compile correctly even if you don't #include --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index ee21554..30052dd 100644 --- a/stb_image.h +++ b/stb_image.h @@ -511,8 +511,8 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch #include #include -#if !defined(STBI_NO_LINEAR) && !defined(STBI_NO_HDR) -#include // ldexp +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow #endif #ifndef STBI_NO_STDIO From 40f43afe5609389fe581ff020ad733a070bf5564 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:40:17 -0800 Subject: [PATCH 78/99] tweak tests --- tests/stblib.dsp | 2 +- tests/test_c_compilation.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/stblib.dsp b/tests/stblib.dsp index f0ede02..ed1742c 100644 --- a/tests/stblib.dsp +++ b/tests/stblib.dsp @@ -65,7 +65,7 @@ LINK32=link.exe # 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 /I "..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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" diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index 3dd6c16..40bc5a4 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -1,4 +1,3 @@ -#include "stb_sprintf.h" #define STB_SPRINTF_IMPLEMENTATION #include "stb_sprintf.h" @@ -13,7 +12,6 @@ #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 a9672961c96f2a985867db1905bafb378057fd4e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:45:59 -0800 Subject: [PATCH 79/99] more cases of STB_NO_HDR and STB_NO_LINEAR interfering --- stb_image.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 30052dd..f090ed3 100644 --- a/stb_image.h +++ b/stb_image.h @@ -904,7 +904,7 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add) } // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow -#if !defined(STBI_NO_LINEAR) && !defined(STBI_NO_HDR) +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) 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) && @@ -925,7 +925,7 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add) return stbi__malloc(a*b*c + add); } -#if !defined(STBI_NO_LINEAR) && !defined(STBI_NO_HDR) +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) 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; @@ -1130,7 +1130,7 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, return (stbi__uint16 *) result; } -#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR) static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) { if (stbi__vertically_flip_on_load && result != NULL) { From 73990fefe7e44fb12986173fdbd9e5b60ab6bb5e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 05:48:45 -0800 Subject: [PATCH 80/99] update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb5a4f2..ccd0e2d 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,16 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.13b | audio | 5463 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.17b | graphics | 7457 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_image.h](stb_image.h)** | 2.18 | graphics | 7459 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.18 | graphics | 4589 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.08 | graphics | 1559 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.11 | graphics | 624 | simple 2D rectangle packer with decent quality -**[stb_sprintf.h](stb_sprintf.h)** | 1.04 | utility | 1814 | fast sprintf, snprintf for C/C++ +**[stb_sprintf.h](stb_sprintf.h)** | 1.05 | utility | 1833 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.03 | utility | 262 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **[stb_textedit.h](stb_textedit.h)** | 1.12 | user interface | 1404 | 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.08 | 3D graphics | 728 | Fabian "ryg" Giesen's real-time DXT compressor +**[stb_dxt.h](stb_dxt.h)** | 1.08b | 3D graphics | 728 | 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 @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.4 | misc | 186 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 53358 +Total lines of C code: 53379 FAQ From 48168170a12e2a2f222f8df869bd8c6ce5305a51 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 17:05:57 -0800 Subject: [PATCH 81/99] stb_truetype: add STBTT_fmod --- stb_truetype.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 98c8acc..3f2af93 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.18 - public domain +// stb_truetype.h - v1.19 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -47,6 +47,7 @@ // // VERSION HISTORY // +// 1.19 (2018-xx-xx) STBTT_fmod // 1.18 (2018-01-29) add missing function // 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support @@ -440,6 +441,11 @@ int main(int arg, char **argv) #define STBTT_pow(x,y) pow(x,y) #endif + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + #ifndef STBTT_cos #include #define STBTT_cos(x) cos(x) @@ -3932,7 +3938,7 @@ static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float discr = b*b - a*c; if (discr > 0.0) { float rcpna = -1 / a; - float d = (float) sqrt(discr); + float d = (float) STBTT_sqrt(discr); s0 = (b+d) * rcpna; s1 = (b-d) * rcpna; if (s0 >= 0.0 && s0 <= 1.0) @@ -3994,7 +4000,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex orig[1] = y; // make sure y never passes through a vertex of the shape - y_frac = (float) fmod(y, 1.0f); + y_frac = (float) STBTT_fmod(y, 1.0f); if (y_frac < 0.01f) y += 0.01f; else if (y_frac > 0.99f) From 6ba21df503354f447c900b188f71450be694f7ad Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Tue, 30 Jan 2018 17:33:17 -0800 Subject: [PATCH 82/99] update dsp with new compile tests --- tests/stb.dsp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/stb.dsp b/tests/stb.dsp index 8e09df5..5b870c7 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -190,6 +190,34 @@ SOURCE=.\test_c_compilation.c # End Source File # Begin Source File +SOURCE=.\test_c_lexer.c +# End Source File +# Begin Source File + +SOURCE=.\test_dxt.c +# End Source File +# Begin Source File + +SOURCE=.\test_easyfont.c +# End Source File +# Begin Source File + +SOURCE=.\test_image.c +# End Source File +# Begin Source File + +SOURCE=.\test_image_write.c +# End Source File +# Begin Source File + +SOURCE=.\test_perlin.c +# End Source File +# Begin Source File + +SOURCE=.\test_sprintf.c +# End Source File +# Begin Source File + SOURCE=.\test_truetype.c # End Source File # Begin Source File @@ -198,6 +226,10 @@ SOURCE=.\test_vorbis.c # End Source File # Begin Source File +SOURCE=.\test_voxel.c +# End Source File +# Begin Source File + SOURCE=.\textedit_sample.c # End Source File # End Target From 0ba9ff6599083d0d482cb215886a7efd21fe0791 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 31 Jan 2018 07:50:07 -0800 Subject: [PATCH 83/99] stb_image: fix unused variable warning --- stb_image.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index f090ed3..fd7651f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,6 +48,7 @@ LICENSE RECENT REVISION HISTORY: + 2.19 (2018-xx-xx) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes @@ -6894,7 +6895,7 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) static int stbi__psd_is16(stbi__context *s) { - int channelCount, dummy, depth; + int channelCount, depth; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; @@ -6909,8 +6910,8 @@ static int stbi__psd_is16(stbi__context *s) stbi__rewind( s ); return 0; } - dummy = stbi__get32be(s); - dummy = stbi__get32be(s); + (void) stbi__get32be(s); + (void) stbi__get32be(s); depth = stbi__get16be(s); if (depth != 16) { stbi__rewind( s ); From a6796aee404108f185c2cf33f3db120849d479e2 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Wed, 31 Jan 2018 10:46:31 -0800 Subject: [PATCH 84/99] test stb_lib --- tests/stblib.dsp | 2 +- tests/stblib_test.c | 4 ++-- tests/stblib_test_companion.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/stblib.dsp b/tests/stblib.dsp index ed1742c..c43513d 100644 --- a/tests/stblib.dsp +++ b/tests/stblib.dsp @@ -84,7 +84,7 @@ LINK32=link.exe # Name "stblib - Win32 Debug" # Begin Source File -SOURCE=..\stb_lib.h +SOURCE=.\prerelease\stb_lib.h # End Source File # Begin Source File diff --git a/tests/stblib_test.c b/tests/stblib_test.c index af110d2..9f2e176 100644 --- a/tests/stblib_test.c +++ b/tests/stblib_test.c @@ -1,6 +1,6 @@ -#include "stb_lib.h" +#include "prerelease/stb_lib.h" #define STB_LIB_IMPLEMENTATION -#include "stb_lib.h" +#include "prerelease/stb_lib.h" //#define STB_REGEX_IMPLEMENTATION //#include "stb_regex.h" diff --git a/tests/stblib_test_companion.c b/tests/stblib_test_companion.c index e1f7e68..88f233c 100644 --- a/tests/stblib_test_companion.c +++ b/tests/stblib_test_companion.c @@ -1,4 +1,4 @@ //#include "stb_regex.h" //#include "stb_regex.h" -#include "stb_lib.h" -#include "stb_lib.h" +#include "prerelease/stb_lib.h" +#include "prerelease/stb_lib.h" From a77d9213e4a9f670c5c5ea381152067ba3a63c60 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Thu, 1 Feb 2018 03:53:17 -0800 Subject: [PATCH 85/99] stb_vorbis: no dealloca --- stb_vorbis.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index c7d4b84..843a233 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.13b - public domain +// Ogg Vorbis audio decoder - v1.14 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -32,6 +32,7 @@ // manxorist@github saga musix github:infatum // // Partial history: +// 1.14 - 2018/xx/xx - delete bogus dealloca usage // 1.13 - 2018/01/29 - fix truncation of last frame (hopefully) // 1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files // 1.11 - 2017/07/23 - fix MinGW compilation @@ -882,11 +883,7 @@ static int error(vorb *f, enum STBVorbisError e) #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)) From 34f087ce4c5a0d7cb82db75ec504efdca73c48c2 Mon Sep 17 00:00:00 2001 From: Simon Rodriguez Date: Sun, 4 Feb 2018 20:12:20 +0100 Subject: [PATCH 86/99] stb_image_write: fix indexing error when computing PNG filters with the stbi__flip_vertically_on_write on. The PNG filters of the pixels row N are computed using row N-1 of the final image. If the image should be flipped when saving, this corresponds to row N+1 of the initial image. --- stb_image_write.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index eaf5093..1d8440e 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -987,13 +987,14 @@ static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int int i; int type = mymap[filter_type]; unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; for (i = 0; i < n; ++i) { switch (type) { case 0: line_buffer[i] = z[i]; break; case 1: line_buffer[i] = z[i]; break; - case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; - case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; - case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; case 5: line_buffer[i] = z[i]; break; case 6: line_buffer[i] = z[i]; break; } @@ -1002,9 +1003,9 @@ static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int switch (type) { case 0: line_buffer[i] = z[i]; break; case 1: line_buffer[i] = z[i] - z[i-n]; break; - case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; - case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; - case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; } From 6ab920bb6aec30490ea68ab86fbdfb9f2aed9e24 Mon Sep 17 00:00:00 2001 From: Cap Petschulat Date: Mon, 5 Feb 2018 15:28:04 +0900 Subject: [PATCH 87/99] stb_image_write: fix png compression level typos --- stb_image_write.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index eaf5093..a5a2df7 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -95,7 +95,7 @@ USAGE: at the end of the line.) PNG allows you to set the deflate compression level by setting the global - variable 'stbi_write_png_level' (it defaults to 8). + variable 'stbi_write_png_compression_level' (it defaults to 8). HDR expects linear float data. Since the format is always 32-bit rgb(e) data, alpha (if provided) is discarded, and for monochrome data it is @@ -133,7 +133,8 @@ CREDITS: github:poppolopoppo Patrick Boettcher github:xeekworx - + Cap Petschulat + LICENSE See end of file for license information. @@ -154,7 +155,7 @@ extern "C" { #endif STBIWDEF int stbi_write_tga_with_rle; -STBIWDEF int stbi_write_png_comperssion_level; +STBIWDEF int stbi_write_png_compression_level; STBIWDEF int stbi_write_force_png_filter; #ifndef STBI_WRITE_NO_STDIO @@ -234,7 +235,7 @@ STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); #ifdef STB_IMAGE_WRITE_STATIC static stbi__flip_vertically_on_write=0; -static int stbi_write_png_compression level = 8; +static int stbi_write_png_compression_level = 8; static int stbi_write_tga_with_rle = 1; static int stbi_write_force_png_filter = -1; #else From 4eef034d52d2f3e1c9b681e288436724ddc74aab Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:05:20 -0800 Subject: [PATCH 88/99] stb_write_image: fix typos --- stb_image_write.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index eaf5093..182a65f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.08 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.09 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -154,7 +154,7 @@ extern "C" { #endif STBIWDEF int stbi_write_tga_with_rle; -STBIWDEF int stbi_write_png_comperssion_level; +STBIWDEF int stbi_write_png_compression_level; STBIWDEF int stbi_write_force_png_filter; #ifndef STBI_WRITE_NO_STDIO @@ -1476,6 +1476,8 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.09 (2018-xx-xx) + fix typo in zlib quality API 1.08 (2018-01-29) add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter 1.07 (2017-07-24) From dbf0fab1c73c9b983bc07025fc137e4e9a942b7b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:11:39 -0800 Subject: [PATCH 89/99] stb_image_write: credits --- stb_image_write.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 37ffc0d..3a75614 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -134,6 +134,8 @@ CREDITS: Patrick Boettcher github:xeekworx Cap Petschulat + Simon Rodriguez + Ivan Tikhonov LICENSE @@ -234,7 +236,7 @@ STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) #ifdef STB_IMAGE_WRITE_STATIC -static stbi__flip_vertically_on_write=0; +static int stbi__flip_vertically_on_write=0; static int stbi_write_png_compression_level = 8; static int stbi_write_tga_with_rle = 1; static int stbi_write_force_png_filter = -1; From aeb2b4b64de878ce76447ad4481ea6ef682ab4d4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:19:45 -0800 Subject: [PATCH 90/99] tweak handling of STBIWDEF --- stb_image_write.h | 17 ++++++++++++++--- tests/test_cpp_compilation.cpp | 4 +++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 3a75614..39befed 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -45,8 +45,8 @@ 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_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); - int stbi_write_jpg(char const *filename, int w, int h, int comp, const float *data, int quality); void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically @@ -136,6 +136,8 @@ CREDITS: Cap Petschulat Simon Rodriguez Ivan Tikhonov + github:ignotion + Adam Schackart LICENSE @@ -146,19 +148,26 @@ LICENSE #ifndef INCLUDE_STB_IMAGE_WRITE_H #define INCLUDE_STB_IMAGE_WRITE_H +#ifndef STB_IMAGE_WRITE_STATIC #ifdef __cplusplus extern "C" { #endif +#endif +#ifndef STBIWDEF #ifdef STB_IMAGE_WRITE_STATIC #define STBIWDEF static #else #define STBIWDEF extern #endif +#endif +#ifndef STB_IMAGE_WRITE_STATIC +// C++ forbids static forward declarations STBIWDEF int stbi_write_tga_with_rle; STBIWDEF int stbi_write_png_compression_level; STBIWDEF int stbi_write_force_png_filter; +#endif #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); @@ -178,9 +187,11 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); +#ifndef STB_IMAGE_WRITE_STATIC #ifdef __cplusplus } #endif +#endif #endif//INCLUDE_STB_IMAGE_WRITE_H @@ -1480,8 +1491,8 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history - 1.09 (2018-xx-xx) - fix typo in zlib quality API + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ 1.08 (2018-01-29) add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter 1.07 (2017-07-24) diff --git a/tests/test_cpp_compilation.cpp b/tests/test_cpp_compilation.cpp index 138948b..96ecf9d 100644 --- a/tests/test_cpp_compilation.cpp +++ b/tests/test_cpp_compilation.cpp @@ -2,9 +2,11 @@ #define STB_SPRINTF_IMPLEMENTATION #include "stb_sprintf.h" +#define STB_IMAGE_WRITE_STATIC + +#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_TRUETYPE_IMPLEMENTATION #define STB_PERLIN_IMPLEMENTATION -#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_DXT_IMPLEMENATION #define STB_C_LEXER_IMPLEMENTATIOn #define STB_DIVIDE_IMPLEMENTATION From 543ad0c11294051a51775d346bf660e2d87ba36e Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:29:32 -0800 Subject: [PATCH 91/99] stb_image_write: tweak handling of STB_IMAGE_WRITE_STATIC --- stb_image_write.h | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 39befed..c05e958 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -148,25 +148,23 @@ LICENSE #ifndef INCLUDE_STB_IMAGE_WRITE_H #define INCLUDE_STB_IMAGE_WRITE_H -#ifndef STB_IMAGE_WRITE_STATIC -#ifdef __cplusplus -extern "C" { -#endif -#endif - +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' #ifndef STBIWDEF #ifdef STB_IMAGE_WRITE_STATIC -#define STBIWDEF static +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" #else -#define STBIWDEF extern +#define STBIWDEF extern +#endif #endif #endif -#ifndef STB_IMAGE_WRITE_STATIC -// C++ forbids static forward declarations -STBIWDEF int stbi_write_tga_with_rle; -STBIWDEF int stbi_write_png_compression_level; -STBIWDEF int stbi_write_force_png_filter; +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +extern int stbi_write_tga_with_rle; +extern int stbi_write_png_compression_level; +extern int stbi_write_force_png_filter; #endif #ifndef STBI_WRITE_NO_STDIO @@ -187,12 +185,6 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); -#ifndef STB_IMAGE_WRITE_STATIC -#ifdef __cplusplus -} -#endif -#endif - #endif//INCLUDE_STB_IMAGE_WRITE_H #ifdef STB_IMAGE_WRITE_IMPLEMENTATION From b79c8458d3bc81d89b41a247caf09f07af64f81c Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:29:53 -0800 Subject: [PATCH 92/99] stb_vorbis: avoid NaN due to uninitialized variable --- stb_vorbis.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb_vorbis.c b/stb_vorbis.c index 843a233..eca2e9d 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -30,6 +30,7 @@ // Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Phillip Bennefall Rohit Thiago Goulart // manxorist@github saga musix github:infatum +// Timur Gagiev // // Partial history: // 1.14 - 2018/xx/xx - delete bogus dealloca usage @@ -4054,6 +4055,7 @@ static int start_decoder(vorb *f) 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); + memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1); #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); From ac66307576973693366a6200c036801e6269d97b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:41:20 -0800 Subject: [PATCH 93/99] docs --- stb_vorbis.c | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index eca2e9d..dea5e1d 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -33,23 +33,23 @@ // Timur Gagiev // // Partial history: -// 1.14 - 2018/xx/xx - delete bogus dealloca usage -// 1.13 - 2018/01/29 - fix truncation of last frame (hopefully) -// 1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files -// 1.11 - 2017/07/23 - fix MinGW compilation -// 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 -// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) +// 1.14 - 2018-02-11 - delete bogus dealloca usage +// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) +// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files +// 1.11 - 2017-07-23 - fix MinGW compilation +// 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 +// 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 -// 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; +// 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 // // See end of file for full version history. @@ -5362,22 +5362,22 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history - 1.12 - 2017/11/21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files - 1.11 - 2017/07/23 - fix MinGW compilation - 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; + 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files + 1.11 - 2017-07-23 - fix MinGW compilation + 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 - 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API + 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) + 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 - 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 + 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 From cd62aa97143f00e47a0ef47968ae9071fdd69d56 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:42:05 -0800 Subject: [PATCH 94/99] docs --- stb_image.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index fd7651f..19176c0 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.19 (2018-xx-xx) fix warning + 2.19 (2018-02-11) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes @@ -7238,6 +7238,8 @@ STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user /* revision history: + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug 1-bit BMP *_is_16_bit api From 0c11c4f1b607cc4e189be8cc59337aba4e7bb4a4 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:53:29 -0800 Subject: [PATCH 95/99] rework GPOS support for old non-declare-anywhere C --- stb_truetype.h | 93 +++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index c65b799..a08e929 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -29,6 +29,7 @@ // Simon Glass // github:IntellectualKitty // Imanol Celaya +// Daniel Ribeiro Maciel // // Bug/warning reports/fixes: // "Zer" on mollyrocket Fabian "ryg" Giesen @@ -48,7 +49,7 @@ // // VERSION HISTORY // -// 1.19 (2018-xx-xx) STBTT_fmod +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod // 1.18 (2018-01-29) add missing function // 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support @@ -413,7 +414,8 @@ int main(int arg, char **argv) //// INTEGRATION WITH YOUR CODEBASE //// //// The following sections allow you to supply alternate definitions -//// of C library functions used by stb_truetype. +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. #ifdef STB_TRUETYPE_IMPLEMENTATION // #define your own (u)stbtt_int8/16/32 before including to override this @@ -429,7 +431,7 @@ int main(int arg, char **argv) typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h #ifndef STBTT_ifloor #include #define STBTT_ifloor(x) ((int) floor(x)) @@ -2305,9 +2307,10 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp stbtt_int32 l=0, r=glyphCount-1, m; int straw, needle=glyph; while (l <= r) { - m = (l + r) >> 1; stbtt_uint8 *glyphArray = coverageTable + 4; - stbtt_uint16 glyphID = ttUSHORT(glyphArray + 2 * m); + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); straw = glyphID; if (needle < straw) r = m - 1; @@ -2327,8 +2330,9 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp stbtt_int32 l=0, r=rangeCount-1, m; int strawStart, strawEnd, needle=glyph; while (l <= r) { + stbtt_uint8 *rangeRecord; m = (l + r) >> 1; - stbtt_uint8 *rangeRecord = rangeArray + 6 * m; + rangeRecord = rangeArray + 6 * m; strawStart = ttUSHORT(rangeRecord); strawEnd = ttUSHORT(rangeRecord + 2); if (needle < strawStart) @@ -2344,7 +2348,7 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp default: { // There are no other cases. - STBTT_assert(false); + STBTT_assert(0); } break; } @@ -2375,8 +2379,9 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) stbtt_int32 l=0, r=classRangeCount-1, m; int strawStart, strawEnd, needle=glyph; while (l <= r) { + stbtt_uint8 *classRangeRecord; m = (l + r) >> 1; - stbtt_uint8 *classRangeRecord = classRangeRecords + 6 * m; + classRangeRecord = classRangeRecords + 6 * m; strawStart = ttUSHORT(classRangeRecord); strawEnd = ttUSHORT(classRangeRecord + 2); if (needle < strawStart) @@ -2392,7 +2397,7 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) default: { // There are no other cases. - STBTT_assert(false); + STBTT_assert(0); } break; } @@ -2404,18 +2409,24 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i; + if (!info->gpos) return 0; - stbtt_uint8 *data = info->data + info->gpos; + data = info->data + info->gpos; if (ttUSHORT(data+0) != 1) return 0; // Major version 1 if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 - stbtt_uint16 lookupListOffset = ttUSHORT(data+8); - stbtt_uint8 *lookupList = data + lookupListOffset; + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); - stbtt_uint16 lookupCount = ttUSHORT(lookupList); - for (stbtt_int32 i=0; i> 1; - stbtt_uint8 *pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; - stbtt_uint16 secondGlyph = ttUSHORT(pairValue); + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); straw = secondGlyph; if (needle < straw) r = m - 1; @@ -2473,11 +2490,6 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i case 2: { stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); - // TODO: Support more formats. - STBTT_GPOS_TODO_assert(valueFormat1 == 4); - if (valueFormat1 != 4) return 0; - STBTT_GPOS_TODO_assert(valueFormat2 == 0); - if (valueFormat2 != 0) return 0; stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); @@ -2489,6 +2501,12 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i STBTT_assert(glyph1class < class1Count); STBTT_assert(glyph2class < class2Count); + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { stbtt_uint8 *class1Records = table + 16; stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); @@ -2499,15 +2517,17 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i default: { // There are no other cases. - STBTT_assert(false); - } break; + STBTT_assert(0); + break; + }; } } - } break; + break; + }; - default: { + default: // TODO: Implement other stuff. - } break; + break; } } @@ -4735,6 +4755,9 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // FULL VERSION HISTORY // +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support // 1.15 (2017-03-03) make more arguments const // 1.14 (2017-01-16) num-fonts-in-TTC function From af786f98833f478cdbf26e527c8e288db8cb1fa6 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:55:27 -0800 Subject: [PATCH 96/99] update readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ccd0e2d..b9efafc 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,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.13b | audio | 5463 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.18 | graphics | 7459 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.18 | graphics | 4589 | parse, decode, and rasterize characters from truetype fonts -**[stb_image_write.h](stb_image_write.h)** | 1.08 | graphics | 1559 | image writing to disk: PNG, TGA, BMP +**[stb_vorbis.c](stb_vorbis.c)** | 1.14 | audio | 5460 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_image.h](stb_image.h)** | 2.18 | graphics | 7460 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.19 | graphics | 4595 | parse, decode, and rasterize characters from truetype fonts +**[stb_image_write.h](stb_image_write.h)** | 1.09 | graphics | 1561 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.11 | graphics | 624 | simple 2D rectangle packer with decent quality **[stb_sprintf.h](stb_sprintf.h)** | 1.05 | utility | 1833 | fast sprintf, snprintf for C/C++ @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.4 | misc | 186 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 53379 +Total lines of C code: 53385 FAQ From 0707304469dafff6d33c0502991f7470594e0267 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:56:13 -0800 Subject: [PATCH 97/99] update readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b9efafc..6e4e3ad 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,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.14 | audio | 5460 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.18 | graphics | 7460 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**[stb_truetype.h](stb_truetype.h)** | 1.19 | graphics | 4595 | parse, decode, and rasterize characters from truetype fonts -**[stb_image_write.h](stb_image_write.h)** | 1.09 | graphics | 1561 | image writing to disk: PNG, TGA, BMP +**[stb_vorbis.c](stb_vorbis.c)** | 1.14 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_image.h](stb_image.h)** | 2.18 | graphics | 7462 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_truetype.h](stb_truetype.h)** | 1.19 | graphics | 4853 | parse, decode, and rasterize characters from truetype fonts +**[stb_image_write.h](stb_image_write.h)** | 1.09 | graphics | 1568 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 0.11 | graphics | 624 | simple 2D rectangle packer with decent quality **[stb_sprintf.h](stb_sprintf.h)** | 1.05 | utility | 1833 | fast sprintf, snprintf for C/C++ @@ -33,7 +33,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.4 | misc | 186 | quick-and-dirty malloc/free leak-checking Total libraries: 20 -Total lines of C code: 53385 +Total lines of C code: 53654 FAQ From fa2a1d9b3be0733b222fc14a7428e81ce940c2a7 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:57:40 -0800 Subject: [PATCH 98/99] stb_image version number --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 19176c0..d9c21bc 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.18 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: From e6afb9cbae4064da8c3e69af3ff5c4629579c1d2 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 11 Feb 2018 11:57:53 -0800 Subject: [PATCH 99/99] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e4e3ad..f7b8dc2 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.14 | audio | 5462 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.18 | graphics | 7462 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_image.h](stb_image.h)** | 2.19 | graphics | 7462 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.19 | graphics | 4853 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.09 | graphics | 1568 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality