From f0f253375415d500165ae59fe81d190f028bcd1c Mon Sep 17 00:00:00 2001 From: AnthoFoxo Date: Wed, 16 Dec 2020 18:19:03 -0500 Subject: [PATCH 01/76] closes #1063; Fixed files with no comments emitting outofmemory errors --- stb_vorbis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index a8cbfa6..f32fdf6 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3643,7 +3643,7 @@ static int start_decoder(vorb *f) //user comments f->comment_list_length = get32_packet(f); f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length)); - if (f->comment_list == NULL) return error(f, VORBIS_outofmem); + if (f->comment_list == NULL && f->comment_list_length > 0) return error(f, VORBIS_outofmem); for(i=0; i < f->comment_list_length; ++i) { len = get32_packet(f); From b038c11bd5039c5c1acae1a8231ffd412fa2e9b3 Mon Sep 17 00:00:00 2001 From: AnthoFoxo Date: Wed, 16 Dec 2020 18:25:11 -0500 Subject: [PATCH 02/76] updated contributor list --- stb_vorbis.c | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_vorbis.c b/stb_vorbis.c index f32fdf6..ab77bc0 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -33,6 +33,7 @@ // Timur Gagiev Maxwell Koo Peter Waller // github:audinowho Dougall Johnson David Reid // github:Clownacy Pedro J. Estebanez Remi Verschelde +// AnthoFoxo // // Partial history: // 1.20 - 2020-07-11 - several small fixes From 4882970b1c9be1c6b4d721fb18cec235093102e2 Mon Sep 17 00:00:00 2001 From: AnthoFoxo Date: Mon, 25 Jan 2021 20:01:42 -0500 Subject: [PATCH 03/76] vorbis comment list setup_malloc call is guarded --- stb_vorbis.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index ab77bc0..46f5370 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3643,8 +3643,10 @@ static int start_decoder(vorb *f) f->vendor[len] = (char)'\0'; //user comments f->comment_list_length = get32_packet(f); - f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length)); - if (f->comment_list == NULL && f->comment_list_length > 0) return error(f, VORBIS_outofmem); + f->comment_list = NULL; + if (f->comment_list_length > 0) + f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); + if (f->comment_list == NULL) return error(f, VORBIS_outofmem); for(i=0; i < f->comment_list_length; ++i) { len = get32_packet(f); From b7b2aaa587977f19bc23c853371c72e4fdd8404c Mon Sep 17 00:00:00 2001 From: AnthoFoxo Date: Tue, 13 Apr 2021 09:43:41 -0400 Subject: [PATCH 04/76] fixed vorbis comments causing outofmem --- stb_vorbis.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 46f5370..5dff95d 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3645,8 +3645,10 @@ static int start_decoder(vorb *f) f->comment_list_length = get32_packet(f); f->comment_list = NULL; if (f->comment_list_length > 0) - f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); - if (f->comment_list == NULL) return error(f, VORBIS_outofmem); + { + f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); + if (f->comment_list == NULL) return error(f, VORBIS_outofmem); + } for(i=0; i < f->comment_list_length; ++i) { len = get32_packet(f); From 52ad6bd4c920e008c6895901948fc95dd09488a1 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 2 Jul 2021 06:56:34 -0700 Subject: [PATCH 05/76] update stb_vorbis version --- README.md | 4 ++-- stb_vorbis.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 429cdb4..961556e 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,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.20 | audio | 5563 | decode ogg vorbis files from file/memory to float/16-bit signed output +**[stb_vorbis.c](stb_vorbis.c)** | 1.21 | audio | 5569 | decode ogg vorbis files from file/memory to float/16-bit signed output **[stb_image.h](stb_image.h)** | 2.26 | graphics | 7762 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **[stb_truetype.h](stb_truetype.h)** | 1.24 | graphics | 5011 | parse, decode, and rasterize characters from truetype fonts **[stb_image_write.h](stb_image_write.h)** | 1.15 | graphics | 1690 | image writing to disk: PNG, TGA, BMP @@ -43,7 +43,7 @@ library | lastest version | category | LoC | description **[stb_include.h](stb_include.h)** | 0.02 | misc | 295 | implement recursive #include support, particularly for GLSL Total libraries: 21 -Total lines of C code: 56524 +Total lines of C code: 56530 FAQ diff --git a/stb_vorbis.c b/stb_vorbis.c index 5dff95d..6b9be1b 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.20 - public domain +// Ogg Vorbis audio decoder - v1.21 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -36,6 +36,7 @@ // AnthoFoxo // // Partial history: +// 1.21 - 2021-07-02 - fix bug for files with no comments // 1.20 - 2020-07-11 - several small fixes // 1.19 - 2020-02-05 - warnings // 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc. From 6294c6cfa2144d52e78b1f545070bbb5a40cf504 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 15:29:17 -0700 Subject: [PATCH 06/76] Move stb.h to deprecated. It was never designed to be used by anyone but Sean and has numerous problems; new code should definitely not be using this. --- stb.h => deprecated/stb.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename stb.h => deprecated/stb.h (100%) diff --git a/stb.h b/deprecated/stb.h similarity index 100% rename from stb.h rename to deprecated/stb.h From 696cb038a35f0196a6f28d7cdd06749a9536d38b Mon Sep 17 00:00:00 2001 From: Michael Aganier Date: Mon, 14 Jun 2021 14:38:26 -0400 Subject: [PATCH 07/76] stb_sprintf: add attribute format to variadic functions This allows for compiler verification of the format string just like printf. --- stb_sprintf.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 0635360..a009c5d 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -7,6 +7,7 @@ // // Contributors: // Fabian "ryg" Giesen (reformatting) +// github:aganm (attribute format) // // Contributors (bugfixes): // github:d26435 @@ -176,6 +177,16 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): #endif #endif +#if defined(__has_attribute) + #if __has_attribute(format) + #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va))) + #endif +#endif + +#ifndef STBSP__ATTRIBUTE_FORMAT +#define STBSP__ATTRIBUTE_FORMAT(fmt,va) +#endif + #include // for va_list() #include // size_t, ptrdiff_t @@ -190,8 +201,8 @@ typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va); STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va); -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...); -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...); +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4); STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); From 98623b957763afb62fbe7b533762de7b3b23bbb2 Mon Sep 17 00:00:00 2001 From: Alan Hickman Date: Sat, 24 Apr 2021 13:08:03 -0700 Subject: [PATCH 08/76] stb_dxt: Initialize tables at compile time Also fix a "potentially uninitialized variable" warning. This is a modified version of Alan's original PR that keeps the table generator in the file (in case there's interest) and also replaces the expand[] tables with math, since it's trivial. Fixes issue #1117. --- stb_dxt.h | 267 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 191 insertions(+), 76 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index 04666de..b37e543 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -29,6 +29,7 @@ // Kevin Schmidt (#defines for "freestanding" compilation) // github:ppiastucki (BC4 support) // Ignacio Castano - improve DXT endpoint quantization +// Alan Hickman - static table initialization // // LICENSE // @@ -81,14 +82,10 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr #include -#if !defined(STBD_ABS) || !defined(STBI_FABS) +#if !defined(STBI_FABS) #include #endif -#ifndef STBD_ABS -#define STBD_ABS(i) abs(i) -#endif - #ifndef STBD_FABS #define STBD_FABS(x) fabs(x) #endif @@ -98,12 +95,112 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr #define STBD_MEMSET memset #endif -static unsigned char stb__Expand5[32]; -static unsigned char stb__Expand6[64]; -static unsigned char stb__OMatch5[256][2]; -static unsigned char stb__OMatch6[256][2]; -static unsigned char stb__QuantRBTab[256+16]; -static unsigned char stb__QuantGTab[256+16]; +static const unsigned char stb__QuantRBTab[256 + 16] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, + 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, + 24, 24, 24, 24, 24, 33, 33, 33, 33, 33, 33, 33, 33, 33, 41, 41, + 41, 41, 41, 41, 41, 41, 49, 49, 49, 49, 49, 49, 49, 49, 57, 57, + 57, 57, 57, 57, 57, 57, 66, 66, 66, 66, 66, 66, 66, 66, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 82, 82, 82, 82, 82, 82, 82, 82, 90, + 90, 90, 90, 90, 90, 90, 90, 99, 99, 99, 99, 99, 99, 99, 99, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 115, 115, 115, 115, 115, 115, 115, 115, + 123, 123, 123, 123, 123, 123, 123, 123, 132, 132, 132, 132, 132, 132, 132, 132, + 140, 140, 140, 140, 140, 140, 140, 140, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 156, 156, 156, 156, 156, 156, 156, 156, 165, 165, 165, 165, 165, 165, 165, + 165, 173, 173, 173, 173, 173, 173, 173, 173, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 189, 189, 189, 189, 189, 189, 189, 189, 198, 198, 198, 198, 198, 198, + 198, 198, 206, 206, 206, 206, 206, 206, 206, 206, 214, 214, 214, 214, 214, 214, + 214, 214, 222, 222, 222, 222, 222, 222, 222, 222, 222, 231, 231, 231, 231, 231, + 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 247, 247, 247, 247, 247, + 247, 247, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +}; +static const unsigned char stb__QuantGTab[256 + 16] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 20, 24, + 24, 24, 24, 28, 28, 28, 28, 32, 32, 32, 32, 36, 36, 36, 36, 40, + 40, 40, 40, 44, 44, 44, 44, 48, 48, 48, 48, 52, 52, 52, 52, 56, + 56, 56, 56, 60, 60, 60, 60, 65, 65, 65, 65, 69, 69, 69, 69, 73, + 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 85, + 89, 89, 89, 89, 93, 93, 93, 93, 97, 97, 97, 97, 101, 101, 101, 101, + 105, 105, 105, 105, 109, 109, 109, 109, 113, 113, 113, 113, 117, 117, 117, 117, + 121, 121, 121, 121, 125, 125, 125, 125, 130, 130, 130, 130, 134, 134, 134, 134, + 138, 138, 138, 138, 142, 142, 142, 142, 146, 146, 146, 146, 150, 150, 150, 150, + 154, 154, 154, 154, 158, 158, 158, 158, 162, 162, 162, 162, 166, 166, 166, 166, + 170, 170, 170, 170, 170, 174, 174, 174, 174, 178, 178, 178, 178, 182, 182, 182, + 182, 186, 186, 186, 186, 190, 190, 190, 190, 195, 195, 195, 195, 199, 199, 199, + 199, 203, 203, 203, 203, 207, 207, 207, 207, 211, 211, 211, 211, 215, 215, 215, + 215, 219, 219, 219, 219, 223, 223, 223, 223, 227, 227, 227, 227, 231, 231, 231, + 231, 235, 235, 235, 235, 239, 239, 239, 239, 243, 243, 243, 243, 247, 247, 247, + 247, 251, 251, 251, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +}; +static const unsigned char stb__OMatch5[256][2] = { + { 0, 0 }, { 0, 0 }, { 0, 1 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 1 }, + { 1, 1 }, { 2, 0 }, { 2, 0 }, { 0, 4 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 3, 0 }, + { 3, 0 }, { 3, 0 }, { 3, 1 }, { 1, 5 }, { 3, 2 }, { 3, 2 }, { 4, 0 }, { 4, 0 }, + { 4, 1 }, { 4, 1 }, { 4, 2 }, { 4, 2 }, { 4, 2 }, { 3, 5 }, { 5, 1 }, { 5, 1 }, + { 5, 2 }, { 4, 4 }, { 5, 3 }, { 5, 3 }, { 5, 3 }, { 6, 2 }, { 6, 2 }, { 6, 2 }, + { 6, 3 }, { 5, 5 }, { 6, 4 }, { 6, 4 }, { 4, 8 }, { 7, 3 }, { 7, 3 }, { 7, 3 }, + { 7, 4 }, { 7, 4 }, { 7, 4 }, { 7, 5 }, { 5, 9 }, { 7, 6 }, { 7, 6 }, { 8, 4 }, + { 8, 4 }, { 8, 5 }, { 8, 5 }, { 8, 6 }, { 8, 6 }, { 8, 6 }, { 7, 9 }, { 9, 5 }, + { 9, 5 }, { 9, 6 }, { 8, 8 }, { 9, 7 }, { 9, 7 }, { 9, 7 }, { 10, 6 }, { 10, 6 }, + { 10, 6 }, { 10, 7 }, { 9, 9 }, { 10, 8 }, { 10, 8 }, { 8, 12 }, { 11, 7 }, { 11, 7 }, + { 11, 7 }, { 11, 8 }, { 11, 8 }, { 11, 8 }, { 11, 9 }, { 9, 13 }, { 11, 10 }, { 11, 10 }, + { 12, 8 }, { 12, 8 }, { 12, 9 }, { 12, 9 }, { 12, 10 }, { 12, 10 }, { 12, 10 }, { 11, 13 }, + { 13, 9 }, { 13, 9 }, { 13, 10 }, { 12, 12 }, { 13, 11 }, { 13, 11 }, { 13, 11 }, { 14, 10 }, + { 14, 10 }, { 14, 10 }, { 14, 11 }, { 13, 13 }, { 14, 12 }, { 14, 12 }, { 12, 16 }, { 15, 11 }, + { 15, 11 }, { 15, 11 }, { 15, 12 }, { 15, 12 }, { 15, 12 }, { 15, 13 }, { 13, 17 }, { 15, 14 }, + { 15, 14 }, { 16, 12 }, { 16, 12 }, { 16, 13 }, { 16, 13 }, { 16, 14 }, { 16, 14 }, { 16, 14 }, + { 15, 17 }, { 17, 13 }, { 17, 13 }, { 17, 14 }, { 16, 16 }, { 17, 15 }, { 17, 15 }, { 17, 15 }, + { 18, 14 }, { 18, 14 }, { 18, 14 }, { 18, 15 }, { 17, 17 }, { 18, 16 }, { 18, 16 }, { 16, 20 }, + { 19, 15 }, { 19, 15 }, { 19, 15 }, { 19, 16 }, { 19, 16 }, { 19, 16 }, { 19, 17 }, { 17, 21 }, + { 19, 18 }, { 19, 18 }, { 20, 16 }, { 20, 16 }, { 20, 17 }, { 20, 17 }, { 20, 18 }, { 20, 18 }, + { 20, 18 }, { 19, 21 }, { 21, 17 }, { 21, 17 }, { 21, 18 }, { 20, 20 }, { 21, 19 }, { 21, 19 }, + { 21, 19 }, { 22, 18 }, { 22, 18 }, { 22, 18 }, { 22, 19 }, { 21, 21 }, { 22, 20 }, { 22, 20 }, + { 20, 24 }, { 23, 19 }, { 23, 19 }, { 23, 19 }, { 23, 20 }, { 23, 20 }, { 23, 20 }, { 23, 21 }, + { 21, 25 }, { 23, 22 }, { 23, 22 }, { 24, 20 }, { 24, 20 }, { 24, 21 }, { 24, 21 }, { 24, 22 }, + { 24, 22 }, { 24, 22 }, { 23, 25 }, { 25, 21 }, { 25, 21 }, { 25, 22 }, { 24, 24 }, { 25, 23 }, + { 25, 23 }, { 25, 23 }, { 26, 22 }, { 26, 22 }, { 26, 22 }, { 26, 23 }, { 25, 25 }, { 26, 24 }, + { 26, 24 }, { 24, 28 }, { 27, 23 }, { 27, 23 }, { 27, 23 }, { 27, 24 }, { 27, 24 }, { 27, 24 }, + { 27, 25 }, { 25, 29 }, { 27, 26 }, { 27, 26 }, { 28, 24 }, { 28, 24 }, { 28, 25 }, { 28, 25 }, + { 28, 26 }, { 28, 26 }, { 28, 26 }, { 27, 29 }, { 29, 25 }, { 29, 25 }, { 29, 26 }, { 28, 28 }, + { 29, 27 }, { 29, 27 }, { 29, 27 }, { 30, 26 }, { 30, 26 }, { 30, 26 }, { 30, 27 }, { 29, 29 }, + { 30, 28 }, { 30, 28 }, { 30, 28 }, { 31, 27 }, { 31, 27 }, { 31, 27 }, { 31, 28 }, { 31, 28 }, + { 31, 28 }, { 31, 29 }, { 31, 29 }, { 31, 30 }, { 31, 30 }, { 31, 30 }, { 31, 31 }, { 31, 31 }, +}; +static const unsigned char stb__OMatch6[256][2] = { + { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, { 1, 1 }, { 2, 0 }, { 2, 1 }, { 3, 0 }, + { 3, 0 }, { 3, 1 }, { 4, 0 }, { 4, 0 }, { 4, 1 }, { 5, 0 }, { 5, 1 }, { 6, 0 }, + { 6, 0 }, { 6, 1 }, { 7, 0 }, { 7, 0 }, { 7, 1 }, { 8, 0 }, { 8, 1 }, { 8, 1 }, + { 8, 2 }, { 9, 1 }, { 9, 2 }, { 9, 2 }, { 9, 3 }, { 10, 2 }, { 10, 3 }, { 10, 3 }, + { 10, 4 }, { 11, 3 }, { 11, 4 }, { 11, 4 }, { 11, 5 }, { 12, 4 }, { 12, 5 }, { 12, 5 }, + { 12, 6 }, { 13, 5 }, { 13, 6 }, { 8, 16 }, { 13, 7 }, { 14, 6 }, { 14, 7 }, { 9, 17 }, + { 14, 8 }, { 15, 7 }, { 15, 8 }, { 11, 16 }, { 15, 9 }, { 15, 10 }, { 16, 8 }, { 16, 9 }, + { 16, 10 }, { 15, 13 }, { 17, 9 }, { 17, 10 }, { 17, 11 }, { 15, 16 }, { 18, 10 }, { 18, 11 }, + { 18, 12 }, { 16, 16 }, { 19, 11 }, { 19, 12 }, { 19, 13 }, { 17, 17 }, { 20, 12 }, { 20, 13 }, + { 20, 14 }, { 19, 16 }, { 21, 13 }, { 21, 14 }, { 21, 15 }, { 20, 17 }, { 22, 14 }, { 22, 15 }, + { 25, 10 }, { 22, 16 }, { 23, 15 }, { 23, 16 }, { 26, 11 }, { 23, 17 }, { 24, 16 }, { 24, 17 }, + { 27, 12 }, { 24, 18 }, { 25, 17 }, { 25, 18 }, { 28, 13 }, { 25, 19 }, { 26, 18 }, { 26, 19 }, + { 29, 14 }, { 26, 20 }, { 27, 19 }, { 27, 20 }, { 30, 15 }, { 27, 21 }, { 28, 20 }, { 28, 21 }, + { 28, 21 }, { 28, 22 }, { 29, 21 }, { 29, 22 }, { 24, 32 }, { 29, 23 }, { 30, 22 }, { 30, 23 }, + { 25, 33 }, { 30, 24 }, { 31, 23 }, { 31, 24 }, { 27, 32 }, { 31, 25 }, { 31, 26 }, { 32, 24 }, + { 32, 25 }, { 32, 26 }, { 31, 29 }, { 33, 25 }, { 33, 26 }, { 33, 27 }, { 31, 32 }, { 34, 26 }, + { 34, 27 }, { 34, 28 }, { 32, 32 }, { 35, 27 }, { 35, 28 }, { 35, 29 }, { 33, 33 }, { 36, 28 }, + { 36, 29 }, { 36, 30 }, { 35, 32 }, { 37, 29 }, { 37, 30 }, { 37, 31 }, { 36, 33 }, { 38, 30 }, + { 38, 31 }, { 41, 26 }, { 38, 32 }, { 39, 31 }, { 39, 32 }, { 42, 27 }, { 39, 33 }, { 40, 32 }, + { 40, 33 }, { 43, 28 }, { 40, 34 }, { 41, 33 }, { 41, 34 }, { 44, 29 }, { 41, 35 }, { 42, 34 }, + { 42, 35 }, { 45, 30 }, { 42, 36 }, { 43, 35 }, { 43, 36 }, { 46, 31 }, { 43, 37 }, { 44, 36 }, + { 44, 37 }, { 44, 37 }, { 44, 38 }, { 45, 37 }, { 45, 38 }, { 40, 48 }, { 45, 39 }, { 46, 38 }, + { 46, 39 }, { 41, 49 }, { 46, 40 }, { 47, 39 }, { 47, 40 }, { 43, 48 }, { 47, 41 }, { 47, 42 }, + { 48, 40 }, { 48, 41 }, { 48, 42 }, { 47, 45 }, { 49, 41 }, { 49, 42 }, { 49, 43 }, { 47, 48 }, + { 50, 42 }, { 50, 43 }, { 50, 44 }, { 48, 48 }, { 51, 43 }, { 51, 44 }, { 51, 45 }, { 49, 49 }, + { 52, 44 }, { 52, 45 }, { 52, 46 }, { 51, 48 }, { 53, 45 }, { 53, 46 }, { 53, 47 }, { 52, 49 }, + { 54, 46 }, { 54, 47 }, { 57, 42 }, { 54, 48 }, { 55, 47 }, { 55, 48 }, { 58, 43 }, { 55, 49 }, + { 56, 48 }, { 56, 49 }, { 59, 44 }, { 56, 50 }, { 57, 49 }, { 57, 50 }, { 60, 45 }, { 57, 51 }, + { 58, 50 }, { 58, 51 }, { 61, 46 }, { 58, 52 }, { 59, 51 }, { 59, 52 }, { 62, 47 }, { 59, 53 }, + { 60, 52 }, { 60, 53 }, { 60, 53 }, { 60, 54 }, { 61, 53 }, { 61, 54 }, { 61, 54 }, { 61, 55 }, + { 62, 54 }, { 62, 55 }, { 62, 55 }, { 62, 56 }, { 63, 55 }, { 63, 56 }, { 63, 56 }, { 63, 57 }, + { 63, 58 }, { 63, 59 }, { 63, 59 }, { 63, 60 }, { 63, 61 }, { 63, 62 }, { 63, 62 }, { 63, 63 }, +}; static int stb__Mul8Bit(int a, int b) { @@ -117,9 +214,10 @@ static void stb__From16Bit(unsigned char *out, unsigned short v) int gv = (v & 0x07e0) >> 5; int bv = (v & 0x001f) >> 0; - out[0] = stb__Expand5[rv]; - out[1] = stb__Expand6[gv]; - out[2] = stb__Expand5[bv]; + // expand to 8 bits via bit replication + out[0] = (rv * 33) >> 2; + out[1] = (gv * 65) >> 4; + out[2] = (bv * 33) >> 2; out[3] = 0; } @@ -151,35 +249,6 @@ static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char /****************************************************************************/ -// compute table to reproduce constant colors as accurately as possible -static void stb__PrepareOptTable(unsigned char *Table,const unsigned char *expand,int size) -{ - int i,mn,mx; - for (i=0;i<256;i++) { - int bestErr = 256; - for (mn=0;mn> 4)]; @@ -316,7 +385,7 @@ static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *c // The color optimization function. (Clever code, part 1) static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16) { - int mind = 0x7fffffff,maxd = -0x7fffffff; + int mind,maxd; unsigned char *minp, *maxp; double magn; int v_r,v_g,v_b; @@ -398,8 +467,10 @@ static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax1 v_b = (int) (vfb * magn); } + minp = maxp = block; + mind = maxd = block[0]*v_r + block[1]*v_g + block[2]*v_b; // Pick colors at extreme points - for(i=0;i<16;i++) + for(i=1;i<16;i++) { int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b; @@ -418,12 +489,12 @@ static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax1 *pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]); } -static const float midpoints5[32] = { +static const float stb__midpoints5[32] = { 0.015686f, 0.047059f, 0.078431f, 0.111765f, 0.145098f, 0.176471f, 0.207843f, 0.241176f, 0.274510f, 0.305882f, 0.337255f, 0.370588f, 0.403922f, 0.435294f, 0.466667f, 0.5f, 0.533333f, 0.564706f, 0.596078f, 0.629412f, 0.662745f, 0.694118f, 0.725490f, 0.758824f, 0.792157f, 0.823529f, 0.854902f, 0.888235f, 0.921569f, 0.952941f, 0.984314f, 1.0f }; -static const float midpoints6[64] = { +static const float stb__midpoints6[64] = { 0.007843f, 0.023529f, 0.039216f, 0.054902f, 0.070588f, 0.086275f, 0.101961f, 0.117647f, 0.133333f, 0.149020f, 0.164706f, 0.180392f, 0.196078f, 0.211765f, 0.227451f, 0.245098f, 0.262745f, 0.278431f, 0.294118f, 0.309804f, 0.325490f, 0.341176f, 0.356863f, 0.372549f, 0.388235f, 0.403922f, 0.419608f, 0.435294f, 0.450980f, 0.466667f, 0.482353f, 0.500000f, 0.517647f, 0.533333f, 0.549020f, 0.564706f, 0.580392f, 0.596078f, 0.611765f, 0.627451f, 0.643137f, 0.658824f, 0.674510f, 0.690196f, 0.705882f, 0.721569f, 0.737255f, 0.754902f, @@ -435,7 +506,7 @@ static unsigned short stb__Quantize5(float x) unsigned short q; x = x < 0 ? 0 : x > 1 ? 1 : x; // saturate q = (unsigned short)(x * 31); - q += (x > midpoints5[q]); + q += (x > stb__midpoints5[q]); return q; } @@ -444,7 +515,7 @@ static unsigned short stb__Quantize6(float x) unsigned short q; x = x < 0 ? 0 : x > 1 ? 1 : x; // saturate q = (unsigned short)(x * 63); - q += (x > midpoints6[q]); + q += (x > stb__midpoints6[q]); return q; } @@ -654,35 +725,9 @@ static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int } } -static void stb__InitDXT() -{ - int i; - for(i=0;i<32;i++) - stb__Expand5[i] = (unsigned char)((i<<3)|(i>>2)); - - for(i=0;i<64;i++) - stb__Expand6[i] = (unsigned char)((i<<2)|(i>>4)); - - for(i=0;i<256+16;i++) - { - int v = i-8 < 0 ? 0 : i-8 > 255 ? 255 : i-8; - stb__QuantRBTab[i] = stb__Expand5[stb__Mul8Bit(v,31)]; - stb__QuantGTab[i] = stb__Expand6[stb__Mul8Bit(v,63)]; - } - - stb__PrepareOptTable(&stb__OMatch5[0][0],stb__Expand5,32); - stb__PrepareOptTable(&stb__OMatch6[0][0],stb__Expand6,64); -} - 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(); - init=0; - } - if (alpha) { int i; stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4); @@ -710,6 +755,76 @@ void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src) } #endif // STB_DXT_IMPLEMENTATION +// Compile with STB_DXT_IMPLEMENTATION and STB_DXT_GENERATE_TABLES +// defined to generate the tables above. +#ifdef STB_DXT_GENERATE_TABLES +#include + +int main() +{ + int i, j; + const char *quant_names[] = { "stb__QuantRBTab", "stb__QuantGTab" }; + const char *omatch_names[] = { "stb__OMatch5", "stb__OMatch6" }; + int dequant_mults[2] = { 33*4, 65 }; // .4 fixed-point dequant multipliers + + // quant tables (for dither) + for (i=0; i < 2; ++i) { + int quant_mult = i ? 63 : 31; + printf("static const unsigned char %s[256 + 16] = {\n", quant_names[i]); + for (int j = 0; j < 256 + 16; ++j) { + int v = j - 8; + int q, dq; + + v = (v < 0) ? 0 : (v > 255) ? 255 : v; // clamp + q = stb__Mul8Bit(v, quant_mult); // quantize + dq = (q * dequant_mults[i]) >> 4; // dequantize + + if ((j % 16) == 0) printf(" "); // 2 spaces, third is done below + printf(" %3d,", dq); + if ((j % 16) == 15) printf("\n"); + } + printf("};\n"); + } + + // optimal endpoint tables + for (i = 0; i < 2; ++i) { + int dequant = dequant_mults[i]; + int size = i ? 64 : 32; + printf("static const unsigned char %s[256][2] = {\n", omatch_names[i]); + for (int j = 0; j < 256; ++j) { + int mn, mx; + int best_mn = 0, best_mx = 0; + int best_err = 256; + for (mn=0;mn> 4; + int maxe = (mx * dequant) >> 4; + int err = abs(stb__Lerp13(maxe, mine) - j); + + // DX10 spec says that interpolation must be within 3% of "correct" result, + // add this as error term. Normally we'd expect a random distribution of + // +-1.5% error, but nowhere in the spec does it say that the error has to be + // unbiased - better safe than sorry. + err += abs(maxe - mine) * 3 / 100; + + if(err < best_err) { + best_mn = mn; + best_mx = mx; + best_err = err; + } + } + } + if ((j % 8) == 0) printf(" "); // 2 spaces, third is done below + printf(" { %2d, %2d },", best_mx, best_mn); + if ((j % 8) == 7) printf("\n"); + } + printf("};\n"); + } + + return 0; +} +#endif + /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. From ae3ed90b0c9548a69e2da4e3fa0f5e77fd00c4d0 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 16:24:09 -0700 Subject: [PATCH 09/76] stb_dxt: Better error calc for single-color table Don't truncate error as aggressively; easily done, but wanted to keep it separate from the previous change. --- stb_dxt.h | 132 +++++++++++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index b37e543..25d3fba 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -134,72 +134,72 @@ static const unsigned char stb__QuantGTab[256 + 16] = { 247, 251, 251, 251, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }; static const unsigned char stb__OMatch5[256][2] = { - { 0, 0 }, { 0, 0 }, { 0, 1 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 1 }, - { 1, 1 }, { 2, 0 }, { 2, 0 }, { 0, 4 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 3, 0 }, - { 3, 0 }, { 3, 0 }, { 3, 1 }, { 1, 5 }, { 3, 2 }, { 3, 2 }, { 4, 0 }, { 4, 0 }, - { 4, 1 }, { 4, 1 }, { 4, 2 }, { 4, 2 }, { 4, 2 }, { 3, 5 }, { 5, 1 }, { 5, 1 }, - { 5, 2 }, { 4, 4 }, { 5, 3 }, { 5, 3 }, { 5, 3 }, { 6, 2 }, { 6, 2 }, { 6, 2 }, - { 6, 3 }, { 5, 5 }, { 6, 4 }, { 6, 4 }, { 4, 8 }, { 7, 3 }, { 7, 3 }, { 7, 3 }, - { 7, 4 }, { 7, 4 }, { 7, 4 }, { 7, 5 }, { 5, 9 }, { 7, 6 }, { 7, 6 }, { 8, 4 }, - { 8, 4 }, { 8, 5 }, { 8, 5 }, { 8, 6 }, { 8, 6 }, { 8, 6 }, { 7, 9 }, { 9, 5 }, - { 9, 5 }, { 9, 6 }, { 8, 8 }, { 9, 7 }, { 9, 7 }, { 9, 7 }, { 10, 6 }, { 10, 6 }, - { 10, 6 }, { 10, 7 }, { 9, 9 }, { 10, 8 }, { 10, 8 }, { 8, 12 }, { 11, 7 }, { 11, 7 }, - { 11, 7 }, { 11, 8 }, { 11, 8 }, { 11, 8 }, { 11, 9 }, { 9, 13 }, { 11, 10 }, { 11, 10 }, - { 12, 8 }, { 12, 8 }, { 12, 9 }, { 12, 9 }, { 12, 10 }, { 12, 10 }, { 12, 10 }, { 11, 13 }, - { 13, 9 }, { 13, 9 }, { 13, 10 }, { 12, 12 }, { 13, 11 }, { 13, 11 }, { 13, 11 }, { 14, 10 }, - { 14, 10 }, { 14, 10 }, { 14, 11 }, { 13, 13 }, { 14, 12 }, { 14, 12 }, { 12, 16 }, { 15, 11 }, - { 15, 11 }, { 15, 11 }, { 15, 12 }, { 15, 12 }, { 15, 12 }, { 15, 13 }, { 13, 17 }, { 15, 14 }, - { 15, 14 }, { 16, 12 }, { 16, 12 }, { 16, 13 }, { 16, 13 }, { 16, 14 }, { 16, 14 }, { 16, 14 }, - { 15, 17 }, { 17, 13 }, { 17, 13 }, { 17, 14 }, { 16, 16 }, { 17, 15 }, { 17, 15 }, { 17, 15 }, - { 18, 14 }, { 18, 14 }, { 18, 14 }, { 18, 15 }, { 17, 17 }, { 18, 16 }, { 18, 16 }, { 16, 20 }, - { 19, 15 }, { 19, 15 }, { 19, 15 }, { 19, 16 }, { 19, 16 }, { 19, 16 }, { 19, 17 }, { 17, 21 }, - { 19, 18 }, { 19, 18 }, { 20, 16 }, { 20, 16 }, { 20, 17 }, { 20, 17 }, { 20, 18 }, { 20, 18 }, - { 20, 18 }, { 19, 21 }, { 21, 17 }, { 21, 17 }, { 21, 18 }, { 20, 20 }, { 21, 19 }, { 21, 19 }, - { 21, 19 }, { 22, 18 }, { 22, 18 }, { 22, 18 }, { 22, 19 }, { 21, 21 }, { 22, 20 }, { 22, 20 }, - { 20, 24 }, { 23, 19 }, { 23, 19 }, { 23, 19 }, { 23, 20 }, { 23, 20 }, { 23, 20 }, { 23, 21 }, - { 21, 25 }, { 23, 22 }, { 23, 22 }, { 24, 20 }, { 24, 20 }, { 24, 21 }, { 24, 21 }, { 24, 22 }, - { 24, 22 }, { 24, 22 }, { 23, 25 }, { 25, 21 }, { 25, 21 }, { 25, 22 }, { 24, 24 }, { 25, 23 }, - { 25, 23 }, { 25, 23 }, { 26, 22 }, { 26, 22 }, { 26, 22 }, { 26, 23 }, { 25, 25 }, { 26, 24 }, - { 26, 24 }, { 24, 28 }, { 27, 23 }, { 27, 23 }, { 27, 23 }, { 27, 24 }, { 27, 24 }, { 27, 24 }, - { 27, 25 }, { 25, 29 }, { 27, 26 }, { 27, 26 }, { 28, 24 }, { 28, 24 }, { 28, 25 }, { 28, 25 }, - { 28, 26 }, { 28, 26 }, { 28, 26 }, { 27, 29 }, { 29, 25 }, { 29, 25 }, { 29, 26 }, { 28, 28 }, - { 29, 27 }, { 29, 27 }, { 29, 27 }, { 30, 26 }, { 30, 26 }, { 30, 26 }, { 30, 27 }, { 29, 29 }, - { 30, 28 }, { 30, 28 }, { 30, 28 }, { 31, 27 }, { 31, 27 }, { 31, 27 }, { 31, 28 }, { 31, 28 }, - { 31, 28 }, { 31, 29 }, { 31, 29 }, { 31, 30 }, { 31, 30 }, { 31, 30 }, { 31, 31 }, { 31, 31 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, + { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 2, 2 }, { 2, 2 }, { 2, 2 }, + { 2, 2 }, { 2, 2 }, { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, + { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, + { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 }, { 5, 5 }, + { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 6, 6 }, { 6, 6 }, + { 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 6 }, { 6, 6 }, { 7, 7 }, { 7, 7 }, + { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 8, 8 }, { 8, 8 }, + { 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 8, 8 }, { 9, 9 }, + { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 10, 10 }, + { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 }, { 11, 11 }, + { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 12, 12 }, + { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, { 12, 12 }, + { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, + { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, { 14, 14 }, + { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, + { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, + { 16, 16 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, + { 17, 17 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, + { 18, 18 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, + { 19, 19 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, + { 20, 20 }, { 20, 20 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, + { 21, 21 }, { 21, 21 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, + { 22, 22 }, { 22, 22 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, + { 23, 23 }, { 23, 23 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, + { 24, 24 }, { 24, 24 }, { 24, 24 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, + { 25, 25 }, { 25, 25 }, { 25, 25 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, + { 26, 26 }, { 26, 26 }, { 26, 26 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, + { 27, 27 }, { 27, 27 }, { 27, 27 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, + { 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, + { 29, 29 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, { 30, 30 }, { 30, 30 }, { 30, 30 }, { 30, 30 }, + { 30, 30 }, { 30, 30 }, { 30, 30 }, { 30, 30 }, { 31, 31 }, { 31, 31 }, { 31, 31 }, { 31, 31 }, }; static const unsigned char stb__OMatch6[256][2] = { - { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 0 }, { 1, 1 }, { 2, 0 }, { 2, 1 }, { 3, 0 }, - { 3, 0 }, { 3, 1 }, { 4, 0 }, { 4, 0 }, { 4, 1 }, { 5, 0 }, { 5, 1 }, { 6, 0 }, - { 6, 0 }, { 6, 1 }, { 7, 0 }, { 7, 0 }, { 7, 1 }, { 8, 0 }, { 8, 1 }, { 8, 1 }, - { 8, 2 }, { 9, 1 }, { 9, 2 }, { 9, 2 }, { 9, 3 }, { 10, 2 }, { 10, 3 }, { 10, 3 }, - { 10, 4 }, { 11, 3 }, { 11, 4 }, { 11, 4 }, { 11, 5 }, { 12, 4 }, { 12, 5 }, { 12, 5 }, - { 12, 6 }, { 13, 5 }, { 13, 6 }, { 8, 16 }, { 13, 7 }, { 14, 6 }, { 14, 7 }, { 9, 17 }, - { 14, 8 }, { 15, 7 }, { 15, 8 }, { 11, 16 }, { 15, 9 }, { 15, 10 }, { 16, 8 }, { 16, 9 }, - { 16, 10 }, { 15, 13 }, { 17, 9 }, { 17, 10 }, { 17, 11 }, { 15, 16 }, { 18, 10 }, { 18, 11 }, - { 18, 12 }, { 16, 16 }, { 19, 11 }, { 19, 12 }, { 19, 13 }, { 17, 17 }, { 20, 12 }, { 20, 13 }, - { 20, 14 }, { 19, 16 }, { 21, 13 }, { 21, 14 }, { 21, 15 }, { 20, 17 }, { 22, 14 }, { 22, 15 }, - { 25, 10 }, { 22, 16 }, { 23, 15 }, { 23, 16 }, { 26, 11 }, { 23, 17 }, { 24, 16 }, { 24, 17 }, - { 27, 12 }, { 24, 18 }, { 25, 17 }, { 25, 18 }, { 28, 13 }, { 25, 19 }, { 26, 18 }, { 26, 19 }, - { 29, 14 }, { 26, 20 }, { 27, 19 }, { 27, 20 }, { 30, 15 }, { 27, 21 }, { 28, 20 }, { 28, 21 }, - { 28, 21 }, { 28, 22 }, { 29, 21 }, { 29, 22 }, { 24, 32 }, { 29, 23 }, { 30, 22 }, { 30, 23 }, - { 25, 33 }, { 30, 24 }, { 31, 23 }, { 31, 24 }, { 27, 32 }, { 31, 25 }, { 31, 26 }, { 32, 24 }, - { 32, 25 }, { 32, 26 }, { 31, 29 }, { 33, 25 }, { 33, 26 }, { 33, 27 }, { 31, 32 }, { 34, 26 }, - { 34, 27 }, { 34, 28 }, { 32, 32 }, { 35, 27 }, { 35, 28 }, { 35, 29 }, { 33, 33 }, { 36, 28 }, - { 36, 29 }, { 36, 30 }, { 35, 32 }, { 37, 29 }, { 37, 30 }, { 37, 31 }, { 36, 33 }, { 38, 30 }, - { 38, 31 }, { 41, 26 }, { 38, 32 }, { 39, 31 }, { 39, 32 }, { 42, 27 }, { 39, 33 }, { 40, 32 }, - { 40, 33 }, { 43, 28 }, { 40, 34 }, { 41, 33 }, { 41, 34 }, { 44, 29 }, { 41, 35 }, { 42, 34 }, - { 42, 35 }, { 45, 30 }, { 42, 36 }, { 43, 35 }, { 43, 36 }, { 46, 31 }, { 43, 37 }, { 44, 36 }, - { 44, 37 }, { 44, 37 }, { 44, 38 }, { 45, 37 }, { 45, 38 }, { 40, 48 }, { 45, 39 }, { 46, 38 }, - { 46, 39 }, { 41, 49 }, { 46, 40 }, { 47, 39 }, { 47, 40 }, { 43, 48 }, { 47, 41 }, { 47, 42 }, - { 48, 40 }, { 48, 41 }, { 48, 42 }, { 47, 45 }, { 49, 41 }, { 49, 42 }, { 49, 43 }, { 47, 48 }, - { 50, 42 }, { 50, 43 }, { 50, 44 }, { 48, 48 }, { 51, 43 }, { 51, 44 }, { 51, 45 }, { 49, 49 }, - { 52, 44 }, { 52, 45 }, { 52, 46 }, { 51, 48 }, { 53, 45 }, { 53, 46 }, { 53, 47 }, { 52, 49 }, - { 54, 46 }, { 54, 47 }, { 57, 42 }, { 54, 48 }, { 55, 47 }, { 55, 48 }, { 58, 43 }, { 55, 49 }, - { 56, 48 }, { 56, 49 }, { 59, 44 }, { 56, 50 }, { 57, 49 }, { 57, 50 }, { 60, 45 }, { 57, 51 }, - { 58, 50 }, { 58, 51 }, { 61, 46 }, { 58, 52 }, { 59, 51 }, { 59, 52 }, { 62, 47 }, { 59, 53 }, - { 60, 52 }, { 60, 53 }, { 60, 53 }, { 60, 54 }, { 61, 53 }, { 61, 54 }, { 61, 54 }, { 61, 55 }, - { 62, 54 }, { 62, 55 }, { 62, 55 }, { 62, 56 }, { 63, 55 }, { 63, 56 }, { 63, 56 }, { 63, 57 }, - { 63, 58 }, { 63, 59 }, { 63, 59 }, { 63, 60 }, { 63, 61 }, { 63, 62 }, { 63, 62 }, { 63, 63 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 2, 2 }, + { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 }, { 4, 4 }, + { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 }, { 6, 6 }, + { 6, 6 }, { 6, 6 }, { 6, 6 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 7, 7 }, { 8, 8 }, + { 8, 8 }, { 8, 8 }, { 8, 8 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 9, 9 }, { 10, 10 }, + { 10, 10 }, { 10, 10 }, { 10, 10 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 11, 11 }, { 12, 12 }, + { 12, 12 }, { 12, 12 }, { 12, 12 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 13, 13 }, { 14, 14 }, + { 14, 14 }, { 14, 14 }, { 14, 14 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 15, 15 }, { 16, 16 }, + { 16, 16 }, { 16, 16 }, { 16, 16 }, { 16, 16 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, { 17, 17 }, + { 18, 18 }, { 18, 18 }, { 18, 18 }, { 18, 18 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, { 19, 19 }, + { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, { 21, 21 }, + { 22, 22 }, { 22, 22 }, { 22, 22 }, { 22, 22 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, { 23, 23 }, + { 24, 24 }, { 24, 24 }, { 24, 24 }, { 24, 24 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, { 25, 25 }, + { 26, 26 }, { 26, 26 }, { 26, 26 }, { 26, 26 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, { 27, 27 }, + { 28, 28 }, { 28, 28 }, { 28, 28 }, { 28, 28 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, { 29, 29 }, + { 30, 30 }, { 30, 30 }, { 30, 30 }, { 30, 30 }, { 31, 31 }, { 31, 31 }, { 31, 31 }, { 31, 31 }, + { 32, 32 }, { 32, 32 }, { 32, 32 }, { 32, 32 }, { 32, 32 }, { 33, 33 }, { 33, 33 }, { 33, 33 }, + { 33, 33 }, { 34, 34 }, { 34, 34 }, { 34, 34 }, { 34, 34 }, { 35, 35 }, { 35, 35 }, { 35, 35 }, + { 35, 35 }, { 36, 36 }, { 36, 36 }, { 36, 36 }, { 36, 36 }, { 37, 37 }, { 37, 37 }, { 37, 37 }, + { 37, 37 }, { 38, 38 }, { 38, 38 }, { 38, 38 }, { 38, 38 }, { 39, 39 }, { 39, 39 }, { 39, 39 }, + { 39, 39 }, { 40, 40 }, { 40, 40 }, { 40, 40 }, { 40, 40 }, { 41, 41 }, { 41, 41 }, { 41, 41 }, + { 41, 41 }, { 42, 42 }, { 42, 42 }, { 42, 42 }, { 42, 42 }, { 43, 43 }, { 43, 43 }, { 43, 43 }, + { 43, 43 }, { 44, 44 }, { 44, 44 }, { 44, 44 }, { 44, 44 }, { 45, 45 }, { 45, 45 }, { 45, 45 }, + { 45, 45 }, { 46, 46 }, { 46, 46 }, { 46, 46 }, { 46, 46 }, { 47, 47 }, { 47, 47 }, { 47, 47 }, + { 47, 47 }, { 48, 48 }, { 48, 48 }, { 48, 48 }, { 48, 48 }, { 48, 48 }, { 49, 49 }, { 49, 49 }, + { 49, 49 }, { 49, 49 }, { 50, 50 }, { 50, 50 }, { 50, 50 }, { 50, 50 }, { 51, 51 }, { 51, 51 }, + { 51, 51 }, { 51, 51 }, { 52, 52 }, { 52, 52 }, { 52, 52 }, { 52, 52 }, { 53, 53 }, { 53, 53 }, + { 53, 53 }, { 53, 53 }, { 54, 54 }, { 54, 54 }, { 54, 54 }, { 54, 54 }, { 55, 55 }, { 55, 55 }, + { 55, 55 }, { 55, 55 }, { 56, 56 }, { 56, 56 }, { 56, 56 }, { 56, 56 }, { 57, 57 }, { 57, 57 }, + { 57, 57 }, { 57, 57 }, { 58, 58 }, { 58, 58 }, { 58, 58 }, { 58, 58 }, { 59, 59 }, { 59, 59 }, + { 59, 59 }, { 59, 59 }, { 60, 60 }, { 60, 60 }, { 60, 60 }, { 60, 60 }, { 61, 61 }, { 61, 61 }, + { 61, 61 }, { 61, 61 }, { 62, 62 }, { 62, 62 }, { 62, 62 }, { 62, 62 }, { 63, 63 }, { 63, 63 }, }; static int stb__Mul8Bit(int a, int b) @@ -794,7 +794,7 @@ int main() for (int j = 0; j < 256; ++j) { int mn, mx; int best_mn = 0, best_mx = 0; - int best_err = 256; + int best_err = 256 * 100; for (mn=0;mn> 4; @@ -805,7 +805,7 @@ int main() // add this as error term. Normally we'd expect a random distribution of // +-1.5% error, but nowhere in the spec does it say that the error has to be // unbiased - better safe than sorry. - err += abs(maxe - mine) * 3 / 100; + err += abs(maxe - mine) * 3; if(err < best_err) { best_mn = mn; From dc2aa370c07219cd7f29d901d1168f2ff448c789 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 16:37:35 -0700 Subject: [PATCH 10/76] stb_dxt: Remove dithering support. Keep STB_DXT_DITHER so as not to break existing code that tries to enable it, but just leave it permanently off. I originally introduced it somewhat superstitiously because of the RGB565 endpoint resolution but it never improved either perceptual quality or objective quality metrics, and the code is appreciably simpler without it. --- stb_dxt.h | 186 ++++++------------------------------------------------ 1 file changed, 18 insertions(+), 168 deletions(-) diff --git a/stb_dxt.h b/stb_dxt.h index 25d3fba..02a06ae 100644 --- a/stb_dxt.h +++ b/stb_dxt.h @@ -1,4 +1,4 @@ -// stb_dxt.h - v1.10 - DXT1/DXT5 compressor - public domain +// stb_dxt.h - v1.11 - 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 // @@ -10,6 +10,7 @@ // You can turn on dithering and "high quality" using mode. // // version history: +// v1.11 - (ryg) avoid racy global init, better single-color tables, remove dither // v1.10 - (i.c) various small quality improvements // v1.09 - (stb) update documentation re: surprising alpha channel requirement // v1.08 - (stb) fix bug in dxt-with-alpha block @@ -50,7 +51,7 @@ extern "C" { // 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_DITHER 1 // use dithering. was always dubious, now deprecated. does nothing! #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); @@ -82,7 +83,7 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr #include -#if !defined(STBI_FABS) +#if !defined(STBD_FABS) #include #endif @@ -90,49 +91,6 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr #define STBD_FABS(x) fabs(x) #endif -#ifndef STBD_MEMSET -#include -#define STBD_MEMSET memset -#endif - -static const unsigned char stb__QuantRBTab[256 + 16] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, - 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, - 24, 24, 24, 24, 24, 33, 33, 33, 33, 33, 33, 33, 33, 33, 41, 41, - 41, 41, 41, 41, 41, 41, 49, 49, 49, 49, 49, 49, 49, 49, 57, 57, - 57, 57, 57, 57, 57, 57, 66, 66, 66, 66, 66, 66, 66, 66, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 82, 82, 82, 82, 82, 82, 82, 82, 90, - 90, 90, 90, 90, 90, 90, 90, 99, 99, 99, 99, 99, 99, 99, 99, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 115, 115, 115, 115, 115, 115, 115, 115, - 123, 123, 123, 123, 123, 123, 123, 123, 132, 132, 132, 132, 132, 132, 132, 132, - 140, 140, 140, 140, 140, 140, 140, 140, 148, 148, 148, 148, 148, 148, 148, 148, - 148, 156, 156, 156, 156, 156, 156, 156, 156, 165, 165, 165, 165, 165, 165, 165, - 165, 173, 173, 173, 173, 173, 173, 173, 173, 181, 181, 181, 181, 181, 181, 181, - 181, 181, 189, 189, 189, 189, 189, 189, 189, 189, 198, 198, 198, 198, 198, 198, - 198, 198, 206, 206, 206, 206, 206, 206, 206, 206, 214, 214, 214, 214, 214, 214, - 214, 214, 222, 222, 222, 222, 222, 222, 222, 222, 222, 231, 231, 231, 231, 231, - 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 247, 247, 247, 247, 247, - 247, 247, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -}; -static const unsigned char stb__QuantGTab[256 + 16] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, - 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 20, 24, - 24, 24, 24, 28, 28, 28, 28, 32, 32, 32, 32, 36, 36, 36, 36, 40, - 40, 40, 40, 44, 44, 44, 44, 48, 48, 48, 48, 52, 52, 52, 52, 56, - 56, 56, 56, 60, 60, 60, 60, 65, 65, 65, 65, 69, 69, 69, 69, 73, - 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 85, - 89, 89, 89, 89, 93, 93, 93, 93, 97, 97, 97, 97, 101, 101, 101, 101, - 105, 105, 105, 105, 109, 109, 109, 109, 113, 113, 113, 113, 117, 117, 117, 117, - 121, 121, 121, 121, 125, 125, 125, 125, 130, 130, 130, 130, 134, 134, 134, 134, - 138, 138, 138, 138, 142, 142, 142, 142, 146, 146, 146, 146, 150, 150, 150, 150, - 154, 154, 154, 154, 158, 158, 158, 158, 162, 162, 162, 162, 166, 166, 166, 166, - 170, 170, 170, 170, 170, 174, 174, 174, 174, 178, 178, 178, 178, 182, 182, 182, - 182, 186, 186, 186, 186, 190, 190, 190, 190, 195, 195, 195, 195, 199, 199, 199, - 199, 203, 203, 203, 203, 207, 207, 207, 207, 211, 211, 211, 211, 215, 215, 215, - 215, 219, 219, 219, 219, 223, 223, 223, 223, 227, 227, 227, 227, 231, 231, 231, - 231, 235, 235, 235, 235, 239, 239, 239, 239, 243, 243, 243, 243, 247, 247, 247, - 247, 251, 251, 251, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -}; static const unsigned char stb__OMatch5[256][2] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 2, 2 }, { 2, 2 }, { 2, 2 }, @@ -257,36 +215,8 @@ static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned shor stb__Lerp13RGB(color+12, color+4, color+0); } -// Block dithering function. Simply dithers a block to 565 RGB. -// (Floyd-Steinberg) -static void stb__DitherBlock(unsigned char *dest, unsigned char *block) -{ - int err[8],*ep1 = err,*ep2 = err+4, *et; - int ch,y; - - // process channels separately - for (ch=0; ch<3; ++ch) { - unsigned char *bp = block+ch, *dp = dest+ch; - const unsigned char *quant = (ch == 1) ? stb__QuantGTab+8 : stb__QuantRBTab+8; - STBD_MEMSET(err, 0, sizeof(err)); - for(y=0; y<4; ++y) { - dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)]; - ep1[0] = bp[ 0] - dp[ 0]; - dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)]; - ep1[1] = bp[ 4] - dp[ 4]; - dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)]; - ep1[2] = bp[ 8] - dp[ 8]; - dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)]; - ep1[3] = bp[12] - dp[12]; - bp += 16; - dp += 16; - et = ep1, ep1 = ep2, ep2 = et; // swap - } - } -} - // The color matching function -static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color,int dither) +static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color) { unsigned int mask = 0; int dirr = color[0*4+0] - color[1*4+0]; @@ -315,68 +245,14 @@ static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *c halfPoint = (stops[3] + stops[2]); c3Point = (stops[2] + stops[0]); - if(!dither) { - // the version without dithering is straightforward - for (i=15;i>=0;i--) { - int dot = dots[i]*2; - mask <<= 2; + for (i=15;i>=0;i--) { + int dot = dots[i]*2; + mask <<= 2; - if(dot < halfPoint) - mask |= (dot < c0Point) ? 1 : 3; - else - mask |= (dot < c3Point) ? 2 : 0; - } - } else { - // with floyd-steinberg dithering - int err[8],*ep1 = err,*ep2 = err+4; - int *dp = dots, y; - - c0Point <<= 3; - halfPoint <<= 3; - c3Point <<= 3; - for(i=0;i<8;i++) - err[i] = 0; - - for(y=0;y<4;y++) - { - int dot,lmask,step; - - dot = (dp[0] << 4) + (3*ep2[1] + 5*ep2[0]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[0] = dp[0] - stops[step]; - lmask = step; - - dot = (dp[1] << 4) + (7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[1] = dp[1] - stops[step]; - lmask |= step<<2; - - dot = (dp[2] << 4) + (7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[2] = dp[2] - stops[step]; - lmask |= step<<4; - - dot = (dp[3] << 4) + (7*ep1[2] + 5*ep2[3] + ep2[2]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[3] = dp[3] - stops[step]; - lmask |= step<<6; - - dp += 4; - mask |= lmask << (y*8); - { int *et = ep1; ep1 = ep2; ep2 = et; } // swap - } + if(dot < halfPoint) + mask |= (dot < c0Point) ? 1 : 3; + else + mask |= (dot < c3Point) ? 2 : 0; } return mask; @@ -603,12 +479,10 @@ static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, i { unsigned int mask; int i; - int dither; int refinecount; unsigned short max16, min16; - unsigned char dblock[16*4],color[4*4]; + unsigned char color[4*4]; - dither = mode & STB_DXT_DITHER; refinecount = (mode & STB_DXT_HIGHQUAL) ? 2 : 1; // check if block is constant @@ -622,15 +496,11 @@ static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, i max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0]; min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1]; } else { - // first step: compute dithered version for PCA if desired - if(dither) - stb__DitherBlock(dblock,block); - - // second step: pca+map along principal axis - stb__OptimizeColorsBlock(dither ? dblock : block,&max16,&min16); + // first step: PCA+map along principal axis + stb__OptimizeColorsBlock(block,&max16,&min16); if (max16 != min16) { stb__EvalColors(color,max16,min16); - mask = stb__MatchColorsBlock(block,color,dither); + mask = stb__MatchColorsBlock(block,color); } else mask = 0; @@ -638,10 +508,10 @@ static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, i for (i=0;i 255) ? 255 : v; // clamp - q = stb__Mul8Bit(v, quant_mult); // quantize - dq = (q * dequant_mults[i]) >> 4; // dequantize - - if ((j % 16) == 0) printf(" "); // 2 spaces, third is done below - printf(" %3d,", dq); - if ((j % 16) == 15) printf("\n"); - } - printf("};\n"); - } - // optimal endpoint tables for (i = 0; i < 2; ++i) { int dequant = dequant_mults[i]; From 2de22bde0ae1de14ad2d7f098a4643e340b96dd8 Mon Sep 17 00:00:00 2001 From: Valentin Lenhart Date: Wed, 28 Oct 2020 14:13:17 +0100 Subject: [PATCH 11/76] stb_sprintf.h: stdlib.h is not needed va_arg() is in stdarg.h, which is already being included --- stb_sprintf.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index a009c5d..cbe7868 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -187,7 +187,7 @@ PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): #define STBSP__ATTRIBUTE_FORMAT(fmt,va) #endif -#include // for va_list() +#include // for va_arg(), va_list() #include // size_t, ptrdiff_t #ifndef STB_SPRINTF_MIN @@ -211,8 +211,6 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri #ifdef STB_SPRINTF_IMPLEMENTATION -#include // for va_arg() - #define stbsp__uint32 unsigned int #define stbsp__int32 signed int From 02578923d324babc429ad4115e2a22d997f84d74 Mon Sep 17 00:00:00 2001 From: Rafael Sachetto Date: Wed, 27 Jan 2021 15:05:48 -0300 Subject: [PATCH 12/76] Fix compilation warnings in the s390x architeture. Fixes #1082. --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index cbe7868..7396760 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -224,7 +224,7 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri #define stbsp__uint16 unsigned short #ifndef stbsp__uintptr -#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) +#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) #define stbsp__uintptr stbsp__uint64 #else #define stbsp__uintptr stbsp__uint32 From 04007a071cf0ecdeab853186be98617920f324ad Mon Sep 17 00:00:00 2001 From: Jan CW Kroeze Date: Thu, 11 Mar 2021 21:13:25 +0100 Subject: [PATCH 13/76] Note GL blend state for stb_truetype --- stb_truetype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stb_truetype.h b/stb_truetype.h index 62595a1..542a890 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -297,6 +297,8 @@ void my_stbtt_initfont(void) void my_stbtt_print(float x, float y, char *text) { // assume orthographic projection with units = screen pixels, origin at top left + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ftex); glBegin(GL_QUADS); From 067655993a3d0a631e03cd7692607308bd9e1865 Mon Sep 17 00:00:00 2001 From: Doj Date: Wed, 27 Jan 2021 20:39:02 +0300 Subject: [PATCH 14/76] stb_sprintf: fix stbsp_ddtoS64 macro Should use xh argument not ph (which is the name of the variable that it actually gets instantiated with the one time it is used). --- stb_sprintf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_sprintf.h b/stb_sprintf.h index 7396760..3152ff3 100644 --- a/stb_sprintf.h +++ b/stb_sprintf.h @@ -1597,7 +1597,7 @@ static stbsp__uint64 const stbsp__powten[20] = { #define stbsp__ddtoS64(ob, xh, xl) \ { \ double ahi = 0, alo, vh, t; \ - ob = (stbsp__int64)ph; \ + ob = (stbsp__int64)xh; \ vh = (double)ob; \ ahi = (xh - vh); \ t = (ahi - xh); \ From 0afc39f59a96113af1f911f67bdb057785965875 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 17:03:51 -0700 Subject: [PATCH 15/76] stb_truetype: Turn codepoint assert into error check Fixes the bug covered by PR #1066, but with a slightly different fix that's hopefully a bit clearer. --- stb_truetype.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 542a890..e06b867 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1541,12 +1541,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep search += 2; { - stbtt_uint16 offset, start; + stbtt_uint16 offset, start, last; stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) return 0; offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); From a49749a57d993e8d3bcc933f83266d7461435cfa Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 17:08:20 -0700 Subject: [PATCH 16/76] stb_textedit: Docs fix. Fixes issue #1041. --- stb_textedit.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index cd38a25..41afb9e 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -87,8 +87,8 @@ // moderate sizes. The undo system does no memory allocations, so // it grows STB_TexteditState by the worst-case storage which is (in bytes): // -// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT -// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT +// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT +// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT // // // Implementation mode: From 1203eb554b7229cdcdc9fde3826f95a675a0287f Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 17:11:25 -0700 Subject: [PATCH 17/76] stb_image: Fix issue #994. Accidentally introduced during a merge. --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index accef48..0a8622b 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5395,7 +5395,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req } if (psize == 0) { STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original)); - if (info.offset != s->callback_already_read + (s->img_buffer - s->buffer_start)) { + if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) { return stbi__errpuc("bad offset", "Corrupt BMP"); } } From 448bb137e3717bf015b410ca25ed83cc48353050 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 17:18:51 -0700 Subject: [PATCH 18/76] stb_image: Better docs for stbi_info. Fixes #1026. --- stb_image.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 0a8622b..f59d773 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.26 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.27 - 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.27 ( ) document stbi_info better 2.26 (2020-07-13) many minor fixes 2.25 (2020-02-02) fix warnings 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically @@ -176,6 +177,14 @@ RECENT REVISION HISTORY: // // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. // +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// // =========================================================================== // // UNICODE: From c62af8565795222df95f548f31027ec0afb59bb1 Mon Sep 17 00:00:00 2001 From: Jacko Dirks Date: Sat, 15 Aug 2020 17:19:02 +0200 Subject: [PATCH 19/76] stb_image.h: Suppress warnings about out_size, delay_size These two variables are unused on some targets, resulting in warnings. Add STBI_NOTUSED around them to suppress those warnings. --- stb_image.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index f59d773..a5ed6aa 100644 --- a/stb_image.h +++ b/stb_image.h @@ -116,6 +116,8 @@ RECENT REVISION HISTORY: Ryan C. Gordon [reserved] [reserved] DO NOT ADD YOUR NAME HERE + Jacko Dirks + To add your name to the credits, pick a random blank space in the middle and fill it. 80% of merge conflicts on stb PRs are due to people adding their name at the end of the credits. @@ -6786,6 +6788,10 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int stride; int out_size = 0; int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + memset(&g, 0, sizeof(g)); if (delays) { *delays = 0; @@ -7215,8 +7221,8 @@ static int stbi__psd_is16(stbi__context *s) stbi__rewind( s ); return 0; } - (void) stbi__get32be(s); - (void) stbi__get32be(s); + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); depth = stbi__get16be(s); if (depth != 16) { stbi__rewind( s ); From 8c15cc9c79bf6f180d74808657046caf2ec0b445 Mon Sep 17 00:00:00 2001 From: Simon Breuss Date: Tue, 18 May 2021 23:51:25 +0200 Subject: [PATCH 20/76] Adds 16-bit support for pnm files. --- stb_image.h | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/stb_image.h b/stb_image.h index a5ed6aa..3c943a3 100644 --- a/stb_image.h +++ b/stb_image.h @@ -108,7 +108,7 @@ RECENT REVISION HISTORY: Cass Everitt Ryamond Barbiero github:grim210 Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus - Josh Tobin Matthew Gregan github:poppolopoppo + Josh Tobin Simon Breuss Matthew Gregan github:poppolopoppo Julian Raschke Gregory Mullen Christian Floisand github:darealshinji Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 Brad Weinberger Matvey Cherevko [reserved] @@ -935,6 +935,7 @@ static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__pnm_test(stbi__context *s); static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); #endif static @@ -7322,7 +7323,8 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req stbi_uc *out; STBI_NOTUSED(ri); - if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) return 0; if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); @@ -7332,12 +7334,12 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req *y = s->img_y; if (comp) *comp = s->img_n; - if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) return stbi__errpuc("too large", "PNM too large"); - out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); - stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8)); if (req_comp && req_comp != s->img_n) { out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); @@ -7413,12 +7415,21 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) stbi__pnm_skip_whitespace(s, &c); maxv = stbi__pnm_getinteger(s, &c); // read max value - - if (maxv > 255) - return stbi__err("max value > 255", "PPM image not 8-bit"); + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; else - return 1; + return 8; } + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} + #endif static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) @@ -7473,6 +7484,9 @@ static int stbi__is_16_main(stbi__context *s) if (stbi__psd_is16(s)) return 1; #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif return 0; } From 8e8f7d9b690bad933333cc57d05871ab5ca35917 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 17:35:40 -0700 Subject: [PATCH 21/76] stb_image: Update credits, change log --- stb_image.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3c943a3..20050ec 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.27 ( ) document stbi_info better + 2.27 ( ) document stbi_info better, 16-bit PNM support 2.26 (2020-07-13) many minor fixes 2.25 (2020-02-02) fix warnings 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically @@ -90,7 +90,7 @@ RECENT REVISION HISTORY: Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Mikhail Morozov (1-bit BMP) Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) - Arseny Kapoulkine + Arseny Kapoulkine Simon Breuss (16-bit PNM) John-Mark Allen Carmelo J Fdez-Aguera @@ -108,7 +108,7 @@ RECENT REVISION HISTORY: Cass Everitt Ryamond Barbiero github:grim210 Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus - Josh Tobin Simon Breuss Matthew Gregan github:poppolopoppo + Josh Tobin Matthew Gregan github:poppolopoppo Julian Raschke Gregory Mullen Christian Floisand github:darealshinji Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 Brad Weinberger Matvey Cherevko [reserved] From 6199b717bcae770e9bae75696cef6a55f1e22ef1 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Thu, 1 Jul 2021 17:49:11 -0700 Subject: [PATCH 22/76] README: updated supported stb_image and stb_image_write formats --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 961556e..118cc9c 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts. library | lastest version | category | LoC | description --------------------- | ---- | -------- | --- | -------------------------------- **[stb_vorbis.c](stb_vorbis.c)** | 1.21 | audio | 5569 | decode ogg vorbis files from file/memory to float/16-bit signed output -**[stb_image.h](stb_image.h)** | 2.26 | graphics | 7762 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**[stb_image.h](stb_image.h)** | 2.26 | graphics | 7762 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC, PNM **[stb_truetype.h](stb_truetype.h)** | 1.24 | graphics | 5011 | parse, decode, and rasterize characters from truetype fonts -**[stb_image_write.h](stb_image_write.h)** | 1.15 | graphics | 1690 | image writing to disk: PNG, TGA, BMP +**[stb_image_write.h](stb_image_write.h)** | 1.15 | graphics | 1690 | image writing to disk: PNG, TGA, BMP, JPG, HDR **[stb_image_resize.h](stb_image_resize.h)** | 0.96 | graphics | 2631 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 1.00 | graphics | 628 | simple 2D rectangle packer with decent quality **[stb_ds.h](stb_ds.h)** | 0.66 | utility | 1893 | typesafe dynamic array and hash tables for C, will compile in C++ From 6ab6303f98f1ee33abe93b730dbbb5b875abbddd Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 17:50:34 -0700 Subject: [PATCH 23/76] stb_image: Check results of all mallocs. A few were missing. Make sure to always report ouf-of-memory errors. Fixes issue #1056. --- stb_image.h | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/stb_image.h b/stb_image.h index 20050ec..71bd506 100644 --- a/stb_image.h +++ b/stb_image.h @@ -48,7 +48,7 @@ LICENSE RECENT REVISION HISTORY: - 2.27 ( ) document stbi_info better, 16-bit PNM support + 2.27 ( ) document stbi_info better, 16-bit PNM support, bug fixes 2.26 (2020-07-13) many minor fixes 2.25 (2020-02-02) fix warnings 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically @@ -3936,6 +3936,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re { unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); @@ -3948,6 +3949,7 @@ static int stbi__jpeg_test(stbi__context *s) { int r; stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); j->s = s; stbi__setup_jpeg(j); r = stbi__decode_jpeg_header(j, STBI__SCAN_type); @@ -3972,6 +3974,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) { int result; stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); j->s = s; result = stbi__jpeg_info_raw(j, x, y, comp); STBI_FREE(j); @@ -4771,6 +4774,7 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3 // de-interlacing final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; @@ -6354,6 +6358,7 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c // intermediate buffer is RGBA result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); memset(result, 0xff, x*y*4); if (!stbi__pic_load_core(s,x,y,comp, result)) { @@ -6469,6 +6474,7 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) { stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); if (!stbi__gif_header(s, g, comp, 1)) { STBI_FREE(g); stbi__rewind( s ); @@ -6778,6 +6784,17 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i } } +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + 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)) { @@ -6810,12 +6827,8 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, if (out) { void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); - if (NULL == tmp) { - STBI_FREE(g.out); - STBI_FREE(g.history); - STBI_FREE(g.background); - return stbi__errpuc("outofmem", "Out of memory"); - } + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); else { out = (stbi_uc*) tmp; out_size = layers * stride; @@ -6823,13 +6836,19 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, if (delays) { *delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); delays_size = layers * sizeof(int); } } else { out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); out_size = layers * stride; if (delays) { *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); delays_size = layers * sizeof(int); } } From 86b7570cfba845e8209c6aec2d15e487bb1d8bb4 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 18:10:49 -0700 Subject: [PATCH 24/76] stb_image: Fix bug on JPEGs with malformed DC deltas extend_receive implicitly requires n <= 15 (code length); the maximum that actually makes sense for 8-bit baseline JPEG is 11, but 15 is the natural limit for us because the AC coding path stores the number of magnitude bits in a nibble. Check that DC delta bits are in range before attempting to call extend_receive. Fixes issue #1108. --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 71bd506..2fced29 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2158,7 +2158,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); t = stbi__jpeg_huff_decode(j, hdc); - if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); // 0 all the ac values now so we can do it 32-bits at a time memset(data,0,64*sizeof(data[0])); @@ -2215,7 +2215,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__ // first scan for DC coefficient, must be first memset(data,0,64*sizeof(data[0])); // 0 all the ac values now t = stbi__jpeg_huff_decode(j, hdc); - if (t == -1) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); diff = t ? stbi__extend_receive(j, t) : 0; dc = j->img_comp[b].dc_pred + diff; From 265b73bb0baf5aa24f12d733c652086063d54a5d Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 18:28:41 -0700 Subject: [PATCH 25/76] stb_image: Fix lrot definition, small extend_receive tweak Define lrot in a way that doesn't involve UB when n==0. Also, the previous patch ensures that n <= 15 for all callers of stbi__extend_receive, so can remove the (less restrictive) bounds check for 0 <= n < 17 (the bounds of stbi__bmask) entirely. Fixes issue #1065. --- stb_image.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 2fced29..13f9f12 100644 --- a/stb_image.h +++ b/stb_image.h @@ -645,7 +645,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #ifdef STBI_HAS_LROTL #define stbi_lrot(x,y) _lrotl(x,y) #else - #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) #endif #if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) @@ -2104,7 +2104,6 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB k = stbi_lrot(j->code_buffer, n); - if (n < 0 || n >= (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))) return 0; j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; From 6d857933d5a88633bc170fc982d1c0ebaed9faf9 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 18:42:01 -0700 Subject: [PATCH 26/76] stb_image, stb_image_write: Fix compare sign warnings For the stb_image fix, also replace the magic 288 with a more descriptive name while I'm at it. Fixes #1100 --- stb_image.h | 11 ++++++----- stb_image_write.h | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/stb_image.h b/stb_image.h index 13f9f12..8ac86b6 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3993,6 +3993,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) // fast-way is faster to check than jpeg huffman, but slow way is slower #define STBI__ZFAST_BITS 9 // accelerate all cases in default tables #define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet // zlib-style huffman encoding // (jpegs packs from left, zlib from right, so can't share code) @@ -4002,8 +4003,8 @@ typedef struct stbi__uint16 firstcode[16]; int maxcode[17]; stbi__uint16 firstsymbol[16]; - stbi_uc size[288]; - stbi__uint16 value[288]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; } stbi__zhuffman; stbi_inline static int stbi__bitreverse16(int n) @@ -4134,7 +4135,7 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) if (s >= 16) return -1; // invalid code! // code size is s, so: b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; - if (b >= sizeof (z->size)) return -1; // some data was corrupt somewhere! + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. a->code_buffer >>= s; a->num_bits -= s; @@ -4331,7 +4332,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) return 1; } -static const stbi_uc stbi__zdefault_length[288] = +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, @@ -4377,7 +4378,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) } else { if (type == 1) { // use fixed code lengths - if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; } else { if (!stbi__compute_huffman_codes(a)) return 0; diff --git a/stb_image_write.h b/stb_image_write.h index 95943eb..7b5d91f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -397,7 +397,7 @@ static void stbiw__putc(stbi__write_context *s, unsigned char c) static void stbiw__write1(stbi__write_context *s, unsigned char a) { - if (s->buf_used + 1 > sizeof(s->buffer)) + if ((size_t)s->buf_used + 1 > sizeof(s->buffer)) stbiw__write_flush(s); s->buffer[s->buf_used++] = a; } @@ -405,7 +405,7 @@ static void stbiw__write1(stbi__write_context *s, unsigned char a) static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) { int n; - if (s->buf_used + 3 > sizeof(s->buffer)) + if ((size_t)s->buf_used + 3 > sizeof(s->buffer)) stbiw__write_flush(s); n = s->buf_used; s->buf_used = n+3; From 43b32c7babcec25bf7c544220e55bc03b4fd37dc Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 20:59:22 -0700 Subject: [PATCH 27/76] stb_image: Avoid shift of signed values in extend_receive Use an equivalent formulation that has sgn=0 or 1, not 0 or -1. This avoids right-shifting signed values, at least in this place. Fixes issue #1061. --- stb_image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index 8ac86b6..5dd9f32 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2102,12 +2102,12 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) int sgn; if (j->code_bits < n) stbi__grow_buffer_unsafe(j); - sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) k = stbi_lrot(j->code_buffer, n); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; - return k + (stbi__jbias[n] & ~sgn); + return k + (stbi__jbias[n] & (sgn - 1)); } // get some unsigned bits From bb0931744529c218bfa50e9b367c811a31251b75 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 21:09:11 -0700 Subject: [PATCH 28/76] stb_image: Avoid left-shifts of signed values It's implementation-specified behavior. Writing this code and then relying on compiler strength reduction to turn it back into shifts feels extremely silly but it is what it is. Fixes issue #1097. --- stb_image.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 5dd9f32..a50e7bc 100644 --- a/stb_image.h +++ b/stb_image.h @@ -2219,7 +2219,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__ dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; - data[0] = (short) (dc << j->succ_low); + data[0] = (short) (dc * (1 << j->succ_low)); } else { // refinement scan for DC coefficient if (stbi__jpeg_get_bit(j)) @@ -2256,7 +2256,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__ j->code_buffer <<= s; j->code_bits -= s; zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) ((r >> 8) << shift); + data[zig] = (short) ((r >> 8) * (1 << shift)); } else { int rs = stbi__jpeg_huff_decode(j, hac); if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); @@ -2274,7 +2274,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__ } else { k += r; zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) (stbi__extend_receive(j,s) << shift); + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); } } } while (k <= j->spec_end); From d6ab7faec08d6964856472f4ada6adbc0e33ae92 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 21:38:44 -0700 Subject: [PATCH 29/76] stb_image: Update comment As per recent patches, we do support 16-bit PNMs. --- stb_image.h | 1 - 1 file changed, 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index a50e7bc..82b4951 100644 --- a/stb_image.h +++ b/stb_image.h @@ -7321,7 +7321,6 @@ static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) // Known limitations: // Does not support comments in the header section // Does not support ASCII image data (formats P2 and P3) -// Does not support 16-bit-per-channel #ifndef STBI_NO_PNM From 31ba943e3fdff7aff00b55629f747121f802e8c1 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 21:57:25 -0700 Subject: [PATCH 30/76] stb_image: UB fix in stbi__get32le Need to do the second-part shift on uint32 not int. --- stb_image.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 82b4951..01807cc 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1674,7 +1674,8 @@ static int stbi__get16le(stbi__context *s) static stbi__uint32 stbi__get32le(stbi__context *s) { stbi__uint32 z = stbi__get16le(s); - return z + (stbi__get16le(s) << 16); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; } #endif From 4d3b93f5891794a6986c9808fbaaba7ee5a27a10 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 22:01:23 -0700 Subject: [PATCH 31/76] stb_image: Erorr in BMP should error, not assert. There was both the assert and the error check; should just be the error check. Fixes issue #881 (or rather, part of it). --- stb_image.h | 1 - 1 file changed, 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 01807cc..87ae770 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5411,7 +5411,6 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req psize = (info.offset - info.extra_read - info.hsz) >> 2; } if (psize == 0) { - STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original)); if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) { return stbi__errpuc("bad offset", "Corrupt BMP"); } From 55a180671c8be196dabde96baaa7219fc20ecd1f Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 22:31:41 -0700 Subject: [PATCH 32/76] readme: Add "how to use these libs" section Try to be a bit more explicit still. Fixes issue #903, or so I hope. --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 118cc9c..fd3f669 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,24 @@ Total lines of C code: 56530 FAQ --- +#### How do I use these libraries? + +The idea behind single-header file libraries is that they're easy to distribute and deploy +because all the code is contained in a single file. By default, the .h files in here act as +their own header files, i.e. they declare the functions contained in the file but don't +actually result in any code getting compiled. + +So in addition, you should select _exactly one_ C/C++ source file that actually instantiates +the code, preferably a file you're not editing frequently. This file should define a +specific macro (this is documented per-library) to actually enable the function definitions. +For example, to use stb_image, you should have exactly one C/C++ file that doesn't +include stb_image.h regularly, but instead does + + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + +The right macro to define is pointed out right at the top of each of these libraries. + #### What's the license? These libraries are in the public domain. You can do anything you From 618dbd01c81bad6aeb8eb3f37fc3281548678d3c Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 22:52:15 -0700 Subject: [PATCH 33/76] stb_image: Document image size limits Both the buffer size limits and the image dimension limits. Fixes issue #672. --- stb_image.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/stb_image.h b/stb_image.h index 87ae770..3057481 100644 --- a/stb_image.h +++ b/stb_image.h @@ -187,6 +187,24 @@ RECENT REVISION HISTORY: // // returns ok=1 and sets x, y, n if image is a supported format, // // 0 otherwise. // +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// // =========================================================================== // // UNICODE: From 56a7113cd0d0cb3c5be401436de10d7d5e96df6e Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Fri, 2 Jul 2021 23:06:44 -0700 Subject: [PATCH 34/76] stb_image: Reorder format test sequence Put the formats that start with a clear magic number first, the dodgy ones that don't have much of a distinctive header should be tested for later after we've ruled out the clearer ones. Fixes issue #787, hopefully. (Never got a clean repro.) --- stb_image.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/stb_image.h b/stb_image.h index 3057481..6bbcea4 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1117,9 +1117,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order ri->num_channels = 0; - #ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); - #endif + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) #ifndef STBI_NO_PNG if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); #endif @@ -1137,6 +1136,13 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re #ifndef STBI_NO_PIC if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif #ifndef STBI_NO_PNM if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); #endif From 991f1f6419aeba2b69c26aa26befe3ae93259a15 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sat, 3 Jul 2021 00:38:30 -0700 Subject: [PATCH 35/76] stb_image: Fix wrong buffer sizes passed to MultiByteToWideChar Fixes issue #772. --- stb_image.h | 4 ++-- stb_image_write.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index 6bbcea4..54ab97d 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1316,10 +1316,10 @@ static FILE *stbi__fopen(char const *filename, char const *mode) #if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) return 0; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; #if _MSC_VER >= 1400 diff --git a/stb_image_write.h b/stb_image_write.h index 7b5d91f..be9e72d 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -306,10 +306,10 @@ static FILE *stbiw__fopen(char const *filename, char const *mode) #if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) return 0; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; #if _MSC_VER >= 1400 From 2506215e8ab4095d791e95658b26dd708bb13857 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sat, 3 Jul 2021 00:46:04 -0700 Subject: [PATCH 36/76] stb_image: Key Win32 UTF-8 support off _WIN32 not _MSC_VER So that it also works on MinGW. Fixes issue #729. --- stb_image.h | 8 ++++---- stb_image_write.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stb_image.h b/stb_image.h index 54ab97d..59ee9fb 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1298,12 +1298,12 @@ static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, in #ifndef STBI_NO_STDIO -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); #endif -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); @@ -1313,7 +1313,7 @@ STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wch static FILE *stbi__fopen(char const *filename, char const *mode) { FILE *f; -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) @@ -1322,7 +1322,7 @@ static FILE *stbi__fopen(char const *filename, char const *mode) if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; -#if _MSC_VER >= 1400 +#if defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != _wfopen_s(&f, wFilename, wMode)) f = 0; #else diff --git a/stb_image_write.h b/stb_image_write.h index be9e72d..6889b8d 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -285,7 +285,7 @@ static void stbi__stdio_write(void *context, void *data, int size) fwrite(data,1,size,(FILE*) context); } -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) #ifdef __cplusplus #define STBIW_EXTERN extern "C" #else @@ -303,7 +303,7 @@ STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const w static FILE *stbiw__fopen(char const *filename, char const *mode) { FILE *f; -#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) @@ -312,7 +312,7 @@ static FILE *stbiw__fopen(char const *filename, char const *mode) if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; -#if _MSC_VER >= 1400 +#if defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != _wfopen_s(&f, wFilename, wMode)) f = 0; #else From db864a1e309e3e785d1b58879cec83c66444fb2b Mon Sep 17 00:00:00 2001 From: Eugene Golushkov Date: Thu, 1 Oct 2020 03:20:30 +0300 Subject: [PATCH 37/76] stb_image: fix building by MSVC for Windows 10 on ARM --- stb_image.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 59ee9fb..5b2c456 100644 --- a/stb_image.h +++ b/stb_image.h @@ -777,9 +777,12 @@ static int stbi__sse2_available(void) #ifdef STBI_NEON #include -// assume GCC or Clang on ARM targets +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #endif +#endif #ifndef STBI_SIMD_ALIGN #define STBI_SIMD_ALIGN(type, name) type name From 82f9950cea9194f731c42ebbc0678c19c85972af Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sat, 3 Jul 2021 01:00:46 -0700 Subject: [PATCH 38/76] stb_image: Update credits --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 5b2c456..f2e3430 100644 --- a/stb_image.h +++ b/stb_image.h @@ -103,7 +103,7 @@ RECENT REVISION HISTORY: 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 github:snagar + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex Cass Everitt Ryamond Barbiero github:grim210 Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw From 81bcfa9043546dcb0ff5de710002470ac6bb342b Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sat, 3 Jul 2021 23:55:14 -0700 Subject: [PATCH 39/76] stb_image_write: Remove tabs Whitespace-only change. --- stb_image_write.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 6889b8d..3ba0db1 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -296,7 +296,7 @@ STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned in STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { - return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); } #endif @@ -306,15 +306,15 @@ static FILE *stbiw__fopen(char const *filename, char const *mode) #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) return 0; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; #if defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != _wfopen_s(&f, wFilename, wMode)) - f = 0; + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; #else f = _wfopen(wFilename, wMode); #endif @@ -1635,7 +1635,7 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const add HDR output fix monochrome BMP 0.95 (2014-08-17) - add monochrome TGA output + add monochrome TGA output 0.94 (2014-05-31) rename private functions to avoid conflicts with stb_image.h 0.93 (2014-05-27) From 76f55ac210f76592aa73b226c63dff022bd9060b Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 00:16:14 -0700 Subject: [PATCH 40/76] stb_image_write: STBI_WINDOWS_UTF8 -> STBIW_WINDOWS_UTF8 Fixes issue #925. --- stb_image_write.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 3ba0db1..a1634e5 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -178,7 +178,7 @@ STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); -#ifdef STBI_WINDOWS_UTF8 +#ifdef STBIW_WINDOWS_UTF8 STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); #endif #endif @@ -285,7 +285,7 @@ static void stbi__stdio_write(void *context, void *data, int size) fwrite(data,1,size,(FILE*) context); } -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) #ifdef __cplusplus #define STBIW_EXTERN extern "C" #else @@ -303,7 +303,7 @@ STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const w static FILE *stbiw__fopen(char const *filename, char const *mode) { FILE *f; -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) From ba3ba9b78c85abd4ed8ff5d432196f84160bd2b4 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 00:23:38 -0700 Subject: [PATCH 41/76] stb_image_write: Disable HDR writer completely in NO_STDIO build Fixes issue #793, hopefully. --- stb_image_write.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index a1634e5..0dba14c 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -622,6 +622,8 @@ STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) +#ifndef STBI_WRITE_NO_STDIO + static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) { int exponent; @@ -777,7 +779,6 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, return stbi_write_hdr_core(&s, x, y, comp, (float *) data); } -#ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { stbi__write_context s = { 0 }; From a5e40739ac096711e6640babdf3038c8203f9978 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 01:33:53 -0700 Subject: [PATCH 42/76] stb_image_write: Fix define tested for sprintf_s Fixes issue 744. --- 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 0dba14c..271d4ac 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -758,7 +758,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 __STDC_WANT_SECURE_LIB__ +#ifdef __STDC_LIB_EXT1__ len = sprintf_s(buffer, sizeof(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); From 3f671b870ff2f25b439ba36d8490c201c8b2c2bd Mon Sep 17 00:00:00 2001 From: Johannes Schultz Date: Sat, 16 Jan 2021 15:04:26 +0100 Subject: [PATCH 43/76] stb_vorbis: rename BUFFER_SIZE macro to STB_BUFFER_SIZE Fixes issue #1076. --- stb_vorbis.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 6b9be1b..e3ce1e2 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -29,7 +29,7 @@ // Bernhard Wodo Evan Balster github:alxprd // Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Phillip Bennefall Rohit Thiago Goulart -// github:manxorist saga musix github:infatum +// github:manxorist Saga Musix github:infatum // Timur Gagiev Maxwell Koo Peter Waller // github:audinowho Dougall Johnson David Reid // github:Clownacy Pedro J. Estebanez Remi Verschelde @@ -5160,11 +5160,11 @@ static void copy_samples(short *dest, float *src, int len) static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) { - #define BUFFER_SIZE 32 - float buffer[BUFFER_SIZE]; - int i,j,o,n = BUFFER_SIZE; + #define STB_BUFFER_SIZE 32 + float buffer[STB_BUFFER_SIZE]; + int i,j,o,n = STB_BUFFER_SIZE; check_endianness(); - for (o = 0; o < len; o += BUFFER_SIZE) { + for (o = 0; o < len; o += STB_BUFFER_SIZE) { memset(buffer, 0, sizeof(buffer)); if (o + n > len) n = len - o; for (j=0; j < num_c; ++j) { @@ -5181,16 +5181,17 @@ static void compute_samples(int mask, short *output, int num_c, float **data, in output[o+i] = v; } } + #undef STB_BUFFER_SIZE } static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) { - #define BUFFER_SIZE 32 - float buffer[BUFFER_SIZE]; - int i,j,o,n = BUFFER_SIZE >> 1; + #define STB_BUFFER_SIZE 32 + float buffer[STB_BUFFER_SIZE]; + int i,j,o,n = STB_BUFFER_SIZE >> 1; // o is the offset in the source data check_endianness(); - for (o = 0; o < len; o += BUFFER_SIZE >> 1) { + for (o = 0; o < len; o += STB_BUFFER_SIZE >> 1) { // o2 is the offset in the output data int o2 = o << 1; memset(buffer, 0, sizeof(buffer)); @@ -5220,6 +5221,7 @@ static void compute_stereo_samples(short *output, int num_c, float **data, int d output[o2+i] = v; } } + #undef STB_BUFFER_SIZE } static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) From 2e3a6e82228164171b1a4d5b703c40c8d2d42b69 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 02:43:00 -0700 Subject: [PATCH 44/76] stb_vorbis: Move asserts around a bit Not an actual bug, it just looked wonky, but this code runs with code lengths that are verified to be in range (<32) by the length-reading code. Anyway. Fixes issue #901. --- stb_vorbis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index e3ce1e2..8bf886b 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1079,6 +1079,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) // find the first entry for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; if (k == n) { assert(c->sorted_entries == 0); return TRUE; } + assert(len[k] < 32); // no error return required, code reading lens checks this // add to the list add_entry(c, 0, k, m++, len[k], values); // add all available leaves @@ -1092,6 +1093,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) uint32 res; int z = len[i], y; if (z == NO_CODE) continue; + assert(z < 32); // no error return required, code reading lens checks this // find lowest available leaf (should always be earliest, // which is what the specification calls for) // note that this property, and the fact we can never have @@ -1101,12 +1103,10 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) while (z > 0 && !available[z]) --z; if (z == 0) { return FALSE; } res = available[z]; - assert(z >= 0 && z < 32); available[z] = 0; add_entry(c, bit_reverse(res), i, m++, len[i], values); // propagate availability up the tree if (z != len[i]) { - assert(len[i] >= 0 && len[i] < 32); for (y=len[i]; y > z; --y) { assert(available[y] == 0); available[y] = res + (1 << (32-y)); From 6fe053614c6973ae7edf92ef5f9c5bd901adfeeb Mon Sep 17 00:00:00 2001 From: "morlad (iLeitgeb)" Date: Fri, 12 Mar 2021 14:30:06 +0000 Subject: [PATCH 45/76] stb_vorbis: Fix memory leak in stb_vorbis When start_decoder() fails it may already have allocated memory for .vendor and/or .comment_list. Call vorbis_deinit() to free any allocated memory. Fixes issue #1051. --- stb_vorbis.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 8bf886b..0c7c18f 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -33,7 +33,7 @@ // Timur Gagiev Maxwell Koo Peter Waller // github:audinowho Dougall Johnson David Reid // github:Clownacy Pedro J. Estebanez Remi Verschelde -// AnthoFoxo +// AnthoFoxo github:morlat // // Partial history: // 1.21 - 2021-07-02 - fix bug for files with no comments @@ -4513,6 +4513,7 @@ stb_vorbis *stb_vorbis_open_pushdata( *error = VORBIS_need_more_data; else *error = p.error; + vorbis_deinit(&p); return NULL; } f = vorbis_alloc(&p); From 5300d55277cbe1304f7c0d2eb180700e531e698a Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 03:00:17 -0700 Subject: [PATCH 46/76] stb_vorbis: Include alloca.h on Sun targets See PR #1006. --- stb_vorbis.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 0c7c18f..8288d09 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.21 - public domain +// Ogg Vorbis audio decoder - v1.22 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -33,9 +33,10 @@ // Timur Gagiev Maxwell Koo Peter Waller // github:audinowho Dougall Johnson David Reid // github:Clownacy Pedro J. Estebanez Remi Verschelde -// AnthoFoxo github:morlat +// AnthoFoxo github:morlat Gabriel Ravier // // Partial history: +// 1.22 - - various small fixes // 1.21 - 2021-07-02 - fix bug for files with no comments // 1.20 - 2020-07-11 - several small fixes // 1.19 - 2020-02-05 - warnings @@ -581,7 +582,7 @@ enum STBVorbisError #if defined(_MSC_VER) || defined(__MINGW32__) #include #endif - #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__) + #if defined(__linux__) || defined(__linux) || defined(__sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__) #include #endif #else // STB_VORBIS_NO_CRT From 904ecbfc37cfdd0aa86c4cf280ac3f05f52465e3 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 03:15:43 -0700 Subject: [PATCH 47/76] stb_vorbis: Remove spurious assignment to val This is definitely unnecessary, or at least I can't find anything in the Vorbis spec that would indicate anything special happening here. Fixes issue #816. --- stb_vorbis.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 8288d09..8bda695 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -3872,8 +3872,7 @@ static int start_decoder(vorb *f) unsigned int div=1; for (k=0; k < c->dimensions; ++k) { int off = (z / div) % c->lookup_values; - float val = mults[off]; - val = mults[off]*c->delta_value + c->minimum_value + last; + float val = mults[off]*c->delta_value + c->minimum_value + last; c->multiplicands[j*c->dimensions + k] = val; if (c->sequence_p) last = val; From e31da438e84db1d9285ba4933d43db1ec73a9a1b Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 16:08:30 -0700 Subject: [PATCH 48/76] stb_vorbis: Fix unused parameter warnings. Some parameters do not get used, or only when certain config defines are set. Explicitly mark them as unused to make compilers happy. Fixes issue #396. --- stb_vorbis.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stb_vorbis.c b/stb_vorbis.c index 8bda695..38de648 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -649,6 +649,12 @@ typedef signed int int32; typedef float codetype; +#ifdef _MSC_VER +#define STBV_NOTUSED(v) (void)(v) +#else +#define STBV_NOTUSED(v) (void)sizeof(v) +#endif + // @NOTE // // Some arrays below are tagged "//varies", which means it's actually @@ -3072,6 +3078,7 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f for (q=1; q < g->values; ++q) { j = g->sorted_order[q]; #ifndef STB_VORBIS_NO_DEFER_FLOOR + STBV_NOTUSED(step2_flag); if (finalY[j] >= 0) #else if (step2_flag[j]) @@ -3174,6 +3181,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, // WINDOWING + STBV_NOTUSED(left_end); n = f->blocksize[m->blockflag]; map = &f->mapping[m->mapping]; From c817c9621ee306b0360cda5191e1054e1cb70daa Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 16:12:32 -0700 Subject: [PATCH 49/76] stb_vorbis: Add missing cast to uint to avoid UB Fixes issue #574. --- stb_vorbis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 38de648..a998923 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -4579,7 +4579,7 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) header[i] = get8(f); if (f->eof) return 0; if (header[4] != 0) goto invalid; - goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24); + goal = header[22] + (header[23] << 8) + (header[24]<<16) + ((uint32)header[25]<<24); for (i=22; i < 26; ++i) header[i] = 0; crc = 0; From d5613c9511d23b7f0573cfe53b70fa9984d2dd29 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 16:19:46 -0700 Subject: [PATCH 50/76] stb_vorbis: A few UB fixes. Fixes issue #1018. --- stb_vorbis.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index a998923..da1767d 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -1055,7 +1055,7 @@ static float float32_unpack(uint32 x) uint32 sign = x & 0x80000000; uint32 exp = (x & 0x7fe00000) >> 21; double res = sign ? -(double)mantissa : (double)mantissa; - return (float) ldexp((float)res, exp-788); + return (float) ldexp((float)res, (int)exp-788); } @@ -3379,7 +3379,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, // this isn't to spec, but spec would require us to read ahead // and decode the size of all current frames--could be done, // but presumably it's not a commonly used feature - f->current_loc = -n2; // start of first frame is positioned for discard + f->current_loc = 0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around) // we might have to discard samples "from" the next frame too, // if we're lapping a large block then a small at the start? f->discard_samples_deferred = n - right_end; @@ -3963,7 +3963,7 @@ static int start_decoder(vorb *f) if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); } for (k=0; k < 1 << g->class_subclasses[j]; ++k) { - g->subclass_books[j][k] = get_bits(f,8)-1; + g->subclass_books[j][k] = (int16)get_bits(f,8)-1; if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); } } From 39a06413859a8a3f9613145e69ae9494e34b6ff4 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 16:25:33 -0700 Subject: [PATCH 51/76] stb_vorbis: Clarify lifetime of pushdata *output buffers Fixes issue #929. --- stb_vorbis.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stb_vorbis.c b/stb_vorbis.c index da1767d..4cd1699 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -223,6 +223,12 @@ extern int stb_vorbis_decode_frame_pushdata( // channel. In other words, (*output)[0][0] contains the first sample from // the first channel, and (*output)[1][0] contains the first sample from // the second channel. +// +// *output points into stb_vorbis's internal output buffer storage; these +// buffers are owned by stb_vorbis and application code should not free +// them or modify their contents. They are transient and will be overwritten +// once you ask for more data to get decoded, so be sure to grab any data +// you need before then. extern void stb_vorbis_flush_pushdata(stb_vorbis *f); // inform stb_vorbis that your next datablock will not be contiguous with From 0def11ae179ea2ef7216ac1c4e0d42ee9e019892 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 16:35:45 -0700 Subject: [PATCH 52/76] stb_vorbis: Fix some unused variables. Fixes issue #817. --- stb_vorbis.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 4cd1699..7c0e9cd 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -4989,7 +4989,7 @@ unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) // set. whoops! break; } - previous_safe = last_page_loc+1; + //previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging last_page_loc = stb_vorbis_get_file_offset(f); } @@ -5309,8 +5309,6 @@ int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short float **outputs; int len = num_shorts / channels; int n=0; - int z = f->channels; - if (z > channels) z = channels; while (n < len) { int k = f->channel_buffer_end - f->channel_buffer_start; if (n+k >= len) k = len - n; @@ -5329,8 +5327,6 @@ int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, in { float **outputs; int n=0; - int z = f->channels; - if (z > channels) z = channels; while (n < len) { int k = f->channel_buffer_end - f->channel_buffer_start; if (n+k >= len) k = len - n; From 0d47d17002a532fa6dc118b4c95c95e557ac7ef3 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 19:26:31 -0700 Subject: [PATCH 53/76] stb_vorbis: Set error on open_memory with NULL data "Unexpected EOF" seems like the closest match from the error codes we have. Fixes issue #1123. --- stb_vorbis.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 7c0e9cd..51e8eec 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -5100,7 +5100,10 @@ stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const st stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) { stb_vorbis *f, p; - if (data == NULL) return NULL; + if (!data) { + if (error) *error = VORBIS_unexpected_eof; + return NULL; + } vorbis_init(&p, alloc); p.stream = (uint8 *) data; p.stream_end = (uint8 *) data + len; From 70136cd5f1f0f40fc5df529689797f67c3a79c07 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 20:54:18 -0700 Subject: [PATCH 54/76] stb_vorbis: Change imdct_step3_inner_s_loop_ld654 Released Clang 12 generates bad code for the original loop in here. While this is a compiler bug plain and simple, we still have to deal with it. This is related to the SLP vectorizer, and in particular the two reverse subtracts in the butterflies for the second half to avoid unary negates. Use the more regular dataflow that has the unary negates in it (we can at least fold one of them into a constant, namely for A2) and introduce a few temporaries that also make alias analysis (and possible block-level vectorization) a whole let easier while I'm at it. This fixes the codegen issues on Clang 12, which now produces a working decoder, and I expect the single unary negate that we actually gain per iteration of this loop is not a significant perf concern. (There are bigger fish to fry here regardless.) Fixes issue #1152. --- stb_vorbis.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/stb_vorbis.c b/stb_vorbis.c index 51e8eec..534e689 100644 --- a/stb_vorbis.c +++ b/stb_vorbis.c @@ -2592,34 +2592,33 @@ static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, while (z > base) { float k00,k11; + float l00,l11; - k00 = z[-0] - z[-8]; - k11 = z[-1] - z[-9]; - z[-0] = z[-0] + z[-8]; - z[-1] = z[-1] + z[-9]; - z[-8] = k00; - z[-9] = k11 ; + k00 = z[-0] - z[ -8]; + k11 = z[-1] - z[ -9]; + l00 = z[-2] - z[-10]; + l11 = z[-3] - z[-11]; + z[ -0] = z[-0] + z[ -8]; + z[ -1] = z[-1] + z[ -9]; + z[ -2] = z[-2] + z[-10]; + z[ -3] = z[-3] + z[-11]; + z[ -8] = k00; + z[ -9] = k11; + z[-10] = (l00+l11) * A2; + z[-11] = (l11-l00) * A2; - k00 = z[ -2] - z[-10]; - k11 = z[ -3] - z[-11]; - z[ -2] = z[ -2] + z[-10]; - z[ -3] = z[ -3] + z[-11]; - z[-10] = (k00+k11) * A2; - z[-11] = (k11-k00) * A2; - - k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation + k00 = z[ -4] - z[-12]; k11 = z[ -5] - z[-13]; + l00 = z[ -6] - z[-14]; + l11 = z[ -7] - z[-15]; z[ -4] = z[ -4] + z[-12]; z[ -5] = z[ -5] + z[-13]; - z[-12] = k11; - z[-13] = k00; - - k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation - k11 = z[ -7] - z[-15]; z[ -6] = z[ -6] + z[-14]; z[ -7] = z[ -7] + z[-15]; - z[-14] = (k00+k11) * A2; - z[-15] = (k00-k11) * A2; + z[-12] = k11; + z[-13] = -k00; + z[-14] = (l11-l00) * A2; + z[-15] = (l00+l11) * -A2; iter_54(z); iter_54(z-8); From e5fd7f6ce0a187bfdded1d6c1123152b7995dd39 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 21:09:20 -0700 Subject: [PATCH 55/76] stb: Remove stua entirely As per issue 634, Stua "will be deleted from stb.h" soonish. That was 3 years ago, which should be plenty of warning, and the language has been de-facto orphaned and undocumented for a good while longer than that. Fixes issue #634. --- deprecated/stb.h | 1350 ---------------------------------------------- 1 file changed, 1350 deletions(-) diff --git a/deprecated/stb.h b/deprecated/stb.h index 03aec96..cd715e7 100644 --- a/deprecated/stb.h +++ b/deprecated/stb.h @@ -13058,1356 +13058,6 @@ char * stb__string_constant(char *file, int line, char *x) #endif // STB_DEFINE #endif // !STB_DEBUG && !STB_ALWAYS_H - -#ifdef STB_STUA -#error "STUA is no longer supported" -////////////////////////////////////////////////////////////////////////// -// -// stua: little scripting language -// -// define STB_STUA to compile it -// -// see http://nothings.org/stb/stb_stua.html for documentation -// -// basic parsing model: -// -// lexical analysis -// use stb_lex() to parse tokens; keywords get their own tokens -// -// parsing: -// recursive descent parser. too much of a hassle to make an unambiguous -// LR(1) grammar, and one-pass generation is clumsier (recursive descent -// makes it easier to e.g. compile nested functions). on the other hand, -// dictionary syntax required hackery to get extra lookahead. -// -// codegen: -// output into an evaluation tree, using array indices as 'pointers' -// -// run: -// traverse the tree; support for 'break/continue/return' is tricky -// -// garbage collection: -// stu__mark and sweep; explicit stack with non-stu__compile_global_scope roots - -typedef stb_int32 stua_obj; - -typedef stb_idict stua_dict; - -STB_EXTERN void stua_run_script(char *s); -STB_EXTERN void stua_uninit(void); - -extern stua_obj stua_globals; - -STB_EXTERN double stua_number(stua_obj z); - -STB_EXTERN stua_obj stua_getnil(void); -STB_EXTERN stua_obj stua_getfalse(void); -STB_EXTERN stua_obj stua_gettrue(void); -STB_EXTERN stua_obj stua_string(char *z); -STB_EXTERN stua_obj stua_make_number(double d); -STB_EXTERN stua_obj stua_box(int type, void *data, int size); - -enum -{ - STUA_op_negate=129, - STUA_op_shl, STUA_op_ge, - STUA_op_shr, STUA_op_le, - STUA_op_shru, - STUA_op_last -}; - -#define STUA_NO_VALUE 2 // equivalent to a tagged NULL -STB_EXTERN stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c); - -STB_EXTERN stua_obj stua_error(char *err, ...); - -STB_EXTERN stua_obj stua_pushroot(stua_obj o); -STB_EXTERN void stua_poproot ( void ); - - -#ifdef STB_DEFINE -// INTERPRETER - -// 31-bit floating point implementation -// force the (1 << 30) bit (2nd highest bit) to be zero by re-biasing the exponent; -// then shift and set the bottom bit - -static stua_obj stu__floatp(float *f) -{ - unsigned int n = *(unsigned int *) f; - unsigned int e = n & (0xff << 23); - - assert(sizeof(int) == 4 && sizeof(float) == 4); - - if (!e) // zero? - n = n; // no change - else if (e < (64 << 23)) // underflow of the packed encoding? - n = (n & 0x80000000); // signed 0 - else if (e > (190 << 23)) // overflow of the encoding? (or INF or NAN) - n = (n & 0x80000000) + (127 << 23); // new INF encoding - else - n -= 0x20000000; - - // now we need to shuffle the bits so that the spare bit is at the bottom - assert((n & 0x40000000) == 0); - return (n & 0x80000000) + (n << 1) + 1; -} - -static unsigned char stu__getfloat_addend[256]; -static float stu__getfloat(stua_obj v) -{ - unsigned int n; - unsigned int e = ((unsigned int) v) >> 24; - - n = (int) v >> 1; // preserve high bit - n += stu__getfloat_addend[e] << 24; - return *(float *) &n; -} - -stua_obj stua_float(float f) -{ - return stu__floatp(&f); -} - -static void stu__float_init(void) -{ - int i; - stu__getfloat_addend[0] = 0; // do nothing to biased exponent of 0 - for (i=1; i < 127; ++i) - stu__getfloat_addend[i] = 32; // undo the -0x20000000 - stu__getfloat_addend[127] = 64; // convert packed INF to INF (0x3f -> 0x7f) - - for (i=0; i < 128; ++i) // for signed floats, remove the bit we just shifted down - stu__getfloat_addend[128+i] = stu__getfloat_addend[i] - 64; -} - -// Tagged data type implementation - - // TAGS: -#define stu__int_tag 0 // of 2 bits // 00 int -#define stu__float_tag 1 // of 1 bit // 01 float -#define stu__ptr_tag 2 // of 2 bits // 10 boxed - // 11 float - -#define stu__tag(x) ((x) & 3) -#define stu__number(x) (stu__tag(x) != stu__ptr_tag) -#define stu__isint(x) (stu__tag(x) == stu__int_tag) - -#define stu__int(x) ((x) >> 2) -#define stu__float(x) (stu__getfloat(x)) - -#define stu__makeint(v) ((v)*4+stu__int_tag) - -// boxed data, and tag support for boxed data - -enum -{ - STU___float = 1, STU___int = 2, - STU___number = 3, STU___string = 4, - STU___function = 5, STU___dict = 6, - STU___boolean = 7, STU___error = 8, -}; - -// boxed data -#define STU__BOX short type, stua_gc -typedef struct stu__box { STU__BOX; } stu__box; - -stu__box stu__nil = { 0, 1 }; -stu__box stu__true = { STU___boolean, 1, }; -stu__box stu__false = { STU___boolean, 1, }; - -#define stu__makeptr(v) ((stua_obj) (v) + stu__ptr_tag) - -#define stua_nil stu__makeptr(&stu__nil) -#define stua_true stu__makeptr(&stu__true) -#define stua_false stu__makeptr(&stu__false) - -stua_obj stua_getnil(void) { return stua_nil; } -stua_obj stua_getfalse(void) { return stua_false; } -stua_obj stua_gettrue(void) { return stua_true; } - -#define stu__ptr(x) ((stu__box *) ((x) - stu__ptr_tag)) - -#define stu__checkt(t,x) ((t) == STU___float ? ((x) & 1) == stu__float_tag : \ - (t) == STU___int ? stu__isint(x) : \ - (t) == STU___number ? stu__number(x) : \ - stu__tag(x) == stu__ptr_tag && stu__ptr(x)->type == (t)) - -typedef struct -{ - STU__BOX; - void *ptr; -} stu__wrapper; - -// implementation of a 'function' or function + closure - -typedef struct stu__func -{ - STU__BOX; - stua_obj closure_source; // 0 - regular function; 4 - C function - // if closure, pointer to source function - union { - stua_obj closure_data; // partial-application data - void *store; // pointer to free that holds 'code' - stua_obj (*func)(stua_dict *context); - } f; - // closure ends here - short *code; - int num_param; - stua_obj *param; // list of parameter strings -} stu__func; - -// apply this to 'short *code' to get at data -#define stu__const(f) ((stua_obj *) (f)) - -static void stu__free_func(stu__func *f) -{ - if (f->closure_source == 0) free(f->f.store); - if ((stb_uint) f->closure_source <= 4) free(f->param); - free(f); -} - -#define stu__pd(x) ((stua_dict *) stu__ptr(x)) -#define stu__pw(x) ((stu__wrapper *) stu__ptr(x)) -#define stu__pf(x) ((stu__func *) stu__ptr(x)) - - -// garbage-collection - - -static stu__box ** stu__gc_ptrlist; -static stua_obj * stu__gc_root_stack; - -stua_obj stua_pushroot(stua_obj o) { stb_arr_push(stu__gc_root_stack, o); return o; } -void stua_poproot ( void ) { stb_arr_pop(stu__gc_root_stack); } - -static stb_sdict *stu__strings; -static void stu__mark(stua_obj z) -{ - int i; - stu__box *p = stu__ptr(z); - if (p->stua_gc == 1) return; // already marked - assert(p->stua_gc == 0); - p->stua_gc = 1; - switch(p->type) { - case STU___function: { - stu__func *f = (stu__func *) p; - if ((stb_uint) f->closure_source <= 4) { - if (f->closure_source == 0) { - for (i=1; i <= f->code[0]; ++i) - if (!stu__number(((stua_obj *) f->code)[-i])) - stu__mark(((stua_obj *) f->code)[-i]); - } - for (i=0; i < f->num_param; ++i) - stu__mark(f->param[i]); - } else { - stu__mark(f->closure_source); - stu__mark(f->f.closure_data); - } - break; - } - case STU___dict: { - stua_dict *e = (stua_dict *) p; - for (i=0; i < e->limit; ++i) - if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) { - if (!stu__number(e->table[i].k)) stu__mark((int) e->table[i].k); - if (!stu__number(e->table[i].v)) stu__mark((int) e->table[i].v); - } - break; - } - } -} - -static int stu__num_allocs, stu__size_allocs; -static stua_obj stu__flow_val = stua_nil; // used for break & return - -static void stua_gc(int force) -{ - int i; - if (!force && stu__num_allocs == 0 && stu__size_allocs == 0) return; - stu__num_allocs = stu__size_allocs = 0; - //printf("[gc]\n"); - - // clear marks - for (i=0; i < stb_arr_len(stu__gc_ptrlist); ++i) - stu__gc_ptrlist[i]->stua_gc = 0; - - // stu__mark everything reachable - stu__nil.stua_gc = stu__true.stua_gc = stu__false.stua_gc = 1; - stu__mark(stua_globals); - if (!stu__number(stu__flow_val)) - stu__mark(stu__flow_val); - for (i=0; i < stb_arr_len(stu__gc_root_stack); ++i) - if (!stu__number(stu__gc_root_stack[i])) - stu__mark(stu__gc_root_stack[i]); - - // sweep unreachables - for (i=0; i < stb_arr_len(stu__gc_ptrlist);) { - stu__box *z = stu__gc_ptrlist[i]; - if (!z->stua_gc) { - switch (z->type) { - case STU___dict: stb_idict_destroy((stua_dict *) z); break; - case STU___error: free(((stu__wrapper *) z)->ptr); break; - case STU___string: stb_sdict_remove(stu__strings, (char*) ((stu__wrapper *) z)->ptr, NULL); free(z); break; - case STU___function: stu__free_func((stu__func *) z); break; - } - // swap in the last item over this, and repeat - z = stb_arr_pop(stu__gc_ptrlist); - stu__gc_ptrlist[i] = z; - } else - ++i; - } -} - -static void stu__consider_gc(stua_obj x) -{ - if (stu__size_allocs < 100000) return; - if (stu__num_allocs < 10 && stu__size_allocs < 1000000) return; - stb_arr_push(stu__gc_root_stack, x); - stua_gc(0); - stb_arr_pop(stu__gc_root_stack); -} - -static stua_obj stu__makeobj(int type, void *data, int size, int safe_to_gc) -{ - stua_obj x = stu__makeptr(data); - ((stu__box *) data)->type = type; - stb_arr_push(stu__gc_ptrlist, (stu__box *) data); - stu__num_allocs += 1; - stu__size_allocs += size; - if (safe_to_gc) stu__consider_gc(x); - return x; -} - -stua_obj stua_box(int type, void *data, int size) -{ - stu__wrapper *p = (stu__wrapper *) malloc(sizeof(*p)); - p->ptr = data; - return stu__makeobj(type, p, size, 0); -} - -// a stu string can be directly compared for equality, because -// they go into a hash table -stua_obj stua_string(char *z) -{ - stu__wrapper *b = (stu__wrapper *) stb_sdict_get(stu__strings, z); - if (b == NULL) { - int o = stua_box(STU___string, NULL, strlen(z) + sizeof(*b)); - b = stu__pw(o); - stb_sdict_add(stu__strings, z, b); - stb_sdict_getkey(stu__strings, z, (char **) &b->ptr); - } - return stu__makeptr(b); -} - -// stb_obj dictionary is just an stb_idict -static void stu__set(stua_dict *d, stua_obj k, stua_obj v) -{ if (stb_idict_set(d, k, v)) stu__size_allocs += 8; } - -static stua_obj stu__get(stua_dict *d, stua_obj k, stua_obj res) -{ - stb_idict_get_flag(d, k, &res); - return res; -} - -static stua_obj make_string(char *z, int len) -{ - stua_obj s; - char temp[256], *q = (char *) stb_temp(temp, len+1), *p = q; - while (len > 0) { - if (*z == '\\') { - if (z[1] == 'n') *p = '\n'; - else if (z[1] == 'r') *p = '\r'; - else if (z[1] == 't') *p = '\t'; - else *p = z[1]; - p += 1; z += 2; len -= 2; - } else { - *p++ = *z++; len -= 1; - } - } - *p = 0; - s = stua_string(q); - stb_tempfree(temp, q); - return s; -} - -enum token_names -{ - T__none=128, - ST_shl = STUA_op_shl, ST_ge = STUA_op_ge, - ST_shr = STUA_op_shr, ST_le = STUA_op_le, - ST_shru = STUA_op_shru, STU__negate = STUA_op_negate, - ST__reset_numbering = STUA_op_last, - ST_white, - ST_id, ST_float, ST_decimal, ST_hex, ST_char,ST_string, ST_number, - // make sure the keywords come _AFTER_ ST_id, so stb_lex prefer them - ST_if, ST_while, ST_for, ST_eq, ST_nil, - ST_then, ST_do, ST_in, ST_ne, ST_true, - ST_else, ST_break, ST_let, ST_and, ST_false, - ST_elseif, ST_continue, ST_into, ST_or, ST_repeat, - ST_end, ST_as, ST_return, ST_var, ST_func, - ST_catch, ST__frame, - ST__max_terminals, - - STU__defaultparm, STU__seq, -}; - -static stua_dict * stu__globaldict; - stua_obj stua_globals; - -static enum -{ - FLOW_normal, FLOW_continue, FLOW_break, FLOW_return, FLOW_error, -} stu__flow; - -stua_obj stua_error(char *z, ...) -{ - stua_obj a; - char temp[4096], *x; - va_list v; va_start(v,z); vsprintf(temp, z, v); va_end(v); - x = stb_p_strdup(temp); - a = stua_box(STU___error, x, strlen(x)); - stu__flow = FLOW_error; - stu__flow_val = a; - return stua_nil; -} - -double stua_number(stua_obj z) -{ - return stu__tag(z) == stu__int_tag ? stu__int(z) : stu__float(z); -} - -stua_obj stua_make_number(double d) -{ - double e = floor(d); - if (e == d && e < (1 << 29) && e >= -(1 << 29)) - return stu__makeint((int) e); - else - return stua_float((float) d); -} - -stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c) = NULL; - -static stua_obj stu__op(int op, stua_obj a, stua_obj b, stua_obj c) -{ - stua_obj r = STUA_NO_VALUE; - if (op == '+') { - if (stu__checkt(STU___string, a) && stu__checkt(STU___string, b)) { - ;// @TODO: string concatenation - } else if (stu__checkt(STU___function, a) && stu__checkt(STU___dict, b)) { - stu__func *f = (stu__func *) malloc(12); - assert(offsetof(stu__func, code)==12); - f->closure_source = a; - f->f.closure_data = b; - return stu__makeobj(STU___function, f, 16, 1); - } - } - if (stua_overload) r = stua_overload(op,a,b,c); - if (stu__flow != FLOW_error && r == STUA_NO_VALUE) - stua_error("Typecheck for operator %d", op), r=stua_nil; - return r; -} - -#define STU__EVAL2(a,b) \ - a = stu__eval(stu__f[n+1]); if (stu__flow) break; stua_pushroot(a); \ - b = stu__eval(stu__f[n+2]); stua_poproot(); if (stu__flow) break; - -#define STU__FB(op) \ - STU__EVAL2(a,b) \ - if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \ - return ((a) op (b)); \ - if (stu__number(a) && stu__number(b)) \ - return stua_make_number(stua_number(a) op stua_number(b)); \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__F(op) \ - STU__EVAL2(a,b) \ - if (stu__number(a) && stu__number(b)) \ - return stua_make_number(stua_number(a) op stua_number(b)); \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__I(op) \ - STU__EVAL2(a,b) \ - if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \ - return stu__makeint(stu__int(a) op stu__int(b)); \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__C(op) \ - STU__EVAL2(a,b) \ - if (stu__number(a) && stu__number(b)) \ - return (stua_number(a) op stua_number(b)) ? stua_true : stua_false; \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__CE(op) \ - STU__EVAL2(a,b) \ - return (a op b) ? stua_true : stua_false - -static short *stu__f; -static stua_obj stu__f_obj; -static stua_dict *stu__c; -static stua_obj stu__funceval(stua_obj fo, stua_obj co); - -static int stu__cond(stua_obj x) -{ - if (stu__flow) return 0; - if (!stu__checkt(STU___boolean, x)) - x = stu__op('!', x, stua_nil, stua_nil); - if (x == stua_true ) return 1; - if (x == stua_false) return 0; - stu__flow = FLOW_error; - return 0; -} - -// had to manually eliminate tailcall recursion for debugging complex stuff -#define TAILCALL(x) n = (x); goto top; -static stua_obj stu__eval(int n) -{ -top: - if (stu__flow >= FLOW_return) return stua_nil; // is this needed? - if (n < 0) return stu__const(stu__f)[n]; - assert(n != 0 && n != 1); - switch (stu__f[n]) { - stua_obj a,b,c; - case ST_catch: a = stu__eval(stu__f[n+1]); - if (stu__flow == FLOW_error) { a=stu__flow_val; stu__flow = FLOW_normal; } - return a; - case ST_var: b = stu__eval(stu__f[n+2]); if (stu__flow) break; - stu__set(stu__c, stu__const(stu__f)[stu__f[n+1]], b); - return b; - case STU__seq: stu__eval(stu__f[n+1]); if (stu__flow) break; - TAILCALL(stu__f[n+2]); - case ST_if: if (!stu__cond(stu__eval(stu__f[n+1]))) return stua_nil; - TAILCALL(stu__f[n+2]); - case ST_else: a = stu__cond(stu__eval(stu__f[n+1])); - TAILCALL(stu__f[n + 2 + !a]); - #define STU__HANDLE_BREAK \ - if (stu__flow >= FLOW_break) { \ - if (stu__flow == FLOW_break) { \ - a = stu__flow_val; \ - stu__flow = FLOW_normal; \ - stu__flow_val = stua_nil; \ - return a; \ - } \ - return stua_nil; \ - } - case ST_as: stu__eval(stu__f[n+3]); - STU__HANDLE_BREAK - // fallthrough! - case ST_while: a = stua_nil; stua_pushroot(a); - while (stu__cond(stu__eval(stu__f[n+1]))) { - stua_poproot(); - a = stu__eval(stu__f[n+2]); - STU__HANDLE_BREAK - stu__flow = FLOW_normal; // clear 'continue' flag - stua_pushroot(a); - if (stu__f[n+3]) stu__eval(stu__f[n+3]); - STU__HANDLE_BREAK - stu__flow = FLOW_normal; // clear 'continue' flag - } - stua_poproot(); - return a; - case ST_break: stu__flow = FLOW_break; stu__flow_val = stu__eval(stu__f[n+1]); break; - case ST_continue:stu__flow = FLOW_continue; break; - case ST_return: stu__flow = FLOW_return; stu__flow_val = stu__eval(stu__f[n+1]); break; - case ST__frame: return stu__f_obj; - case '[': STU__EVAL2(a,b); - if (stu__checkt(STU___dict, a)) - return stu__get(stu__pd(a), b, stua_nil); - return stu__op(stu__f[n], a, b, stua_nil); - case '=': a = stu__eval(stu__f[n+2]); if (stu__flow) break; - n = stu__f[n+1]; - if (stu__f[n] == ST_id) { - if (!stb_idict_update(stu__c, stu__const(stu__f)[stu__f[n+1]], a)) - if (!stb_idict_update(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], a)) - return stua_error("Assignment to undefined variable"); - } else if (stu__f[n] == '[') { - stua_pushroot(a); - b = stu__eval(stu__f[n+1]); if (stu__flow) { stua_poproot(); break; } - stua_pushroot(b); - c = stu__eval(stu__f[n+2]); stua_poproot(); stua_poproot(); - if (stu__flow) break; - if (!stu__checkt(STU___dict, b)) return stua_nil; - stu__set(stu__pd(b), c, a); - } else { - return stu__op(stu__f[n], stu__eval(n), a, stua_nil); - } - return a; - case STU__defaultparm: - a = stu__eval(stu__f[n+2]); - stu__flow = FLOW_normal; - if (stb_idict_add(stu__c, stu__const(stu__f)[stu__f[n+1]], a)) - stu__size_allocs += 8; - return stua_nil; - case ST_id: a = stu__get(stu__c, stu__const(stu__f)[stu__f[n+1]], STUA_NO_VALUE); // try local variable - return a != STUA_NO_VALUE // else try stu__compile_global_scope variable - ? a : stu__get(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], stua_nil); - case STU__negate:a = stu__eval(stu__f[n+1]); if (stu__flow) break; - return stu__isint(a) ? -a : stu__op(stu__f[n], a, stua_nil, stua_nil); - case '~': a = stu__eval(stu__f[n+1]); if (stu__flow) break; - return stu__isint(a) ? (~a)&~3 : stu__op(stu__f[n], a, stua_nil, stua_nil); - case '!': a = stu__eval(stu__f[n+1]); if (stu__flow) break; - a = stu__cond(a); if (stu__flow) break; - return a ? stua_true : stua_false; - case ST_eq: STU__CE(==); case ST_le: STU__C(<=); case '<': STU__C(<); - case ST_ne: STU__CE(!=); case ST_ge: STU__C(>=); case '>': STU__C(>); - case '+' : STU__FB(+); case '*': STU__F(*); case '&': STU__I(&); case ST_shl: STU__I(<<); - case '-' : STU__FB(-); case '/': STU__F(/); case '|': STU__I(|); case ST_shr: STU__I(>>); - case '%': STU__I(%); case '^': STU__I(^); - case ST_shru: STU__EVAL2(a,b); - if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) - return stu__makeint((unsigned) stu__int(a) >> stu__int(b)); - return stu__op(stu__f[n], a,b, stua_nil); - case ST_and: a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break; - return a ? stu__eval(stu__f[n+2]) : a; - case ST_or : a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break; - return a ? b : stu__eval(stu__f[n+2]); - case'(':case':': STU__EVAL2(a,b); - if (!stu__checkt(STU___function, a)) - return stu__op(stu__f[n], a,b, stua_nil); - if (!stu__checkt(STU___dict, b)) - return stua_nil; - if (stu__f[n] == ':') - b = stu__makeobj(STU___dict, stb_idict_copy(stu__pd(b)), stb_idict_memory_usage(stu__pd(b)), 0); - a = stu__funceval(a,b); - return a; - case '{' : { - stua_dict *d; - d = stb_idict_new_size(stu__f[n+1] > 40 ? 64 : 16); - if (d == NULL) - return stua_nil; // breakpoint fodder - c = stu__makeobj(STU___dict, d, 32, 1); - stua_pushroot(c); - a = stu__f[n+1]; - for (b=0; b < a; ++b) { - stua_obj x = stua_pushroot(stu__eval(stu__f[n+2 + b*2 + 0])); - stua_obj y = stu__eval(stu__f[n+2 + b*2 + 1]); - stua_poproot(); - if (stu__flow) { stua_poproot(); return stua_nil; } - stu__set(d, x, y); - } - stua_poproot(); - return c; - } - default: if (stu__f[n] < 0) return stu__const(stu__f)[stu__f[n]]; - assert(0); /* NOTREACHED */ // internal error! - } - return stua_nil; -} - -int stb__stua_nesting; -static stua_obj stu__funceval(stua_obj fo, stua_obj co) -{ - stu__func *f = stu__pf(fo); - stua_dict *context = stu__pd(co); - int i,j; - stua_obj p; - short *tf = stu__f; // save previous function - stua_dict *tc = stu__c; - - if (stu__flow == FLOW_error) return stua_nil; - assert(stu__flow == FLOW_normal); - - stua_pushroot(fo); - stua_pushroot(co); - stu__consider_gc(stua_nil); - - while ((stb_uint) f->closure_source > 4) { - // add data from closure to context - stua_dict *e = (stua_dict *) stu__pd(f->f.closure_data); - for (i=0; i < e->limit; ++i) - if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) - if (stb_idict_add(context, e->table[i].k, e->table[i].v)) - stu__size_allocs += 8; - // use add so if it's already defined, we don't override it; that way - // explicit parameters win over applied ones, and most recent applications - // win over previous ones - f = stu__pf(f->closure_source); - } - - for (j=0, i=0; i < f->num_param; ++i) - // if it doesn't already exist, add it from the numbered parameters - if (stb_idict_add(context, f->param[i], stu__get(context, stu__int(j), stua_nil))) - ++j; - - // @TODO: if (stu__get(context, stu__int(f->num_param+1)) != STUA_NO_VALUE) // error: too many parameters - // @TODO: ditto too few parameters - - if (f->closure_source == 4) - p = f->f.func(context); - else { - stu__f = f->code, stu__c = context; - stu__f_obj = co; - ++stb__stua_nesting; - if (stu__f[1]) - p = stu__eval(stu__f[1]); - else - p = stua_nil; - --stb__stua_nesting; - stu__f = tf, stu__c = tc; // restore previous function - if (stu__flow == FLOW_return) { - stu__flow = FLOW_normal; - p = stu__flow_val; - stu__flow_val = stua_nil; - } - } - - stua_poproot(); - stua_poproot(); - - return p; -} - -// Parser - -static int stu__tok; -static stua_obj stu__tokval; - -static char *stu__curbuf, *stu__bufstart; - -static stb_matcher *stu__lex_matcher; - -static unsigned char stu__prec[ST__max_terminals], stu__end[ST__max_terminals]; - -static void stu__nexttoken(void) -{ - int len; - -retry: - stu__tok = stb_lex(stu__lex_matcher, stu__curbuf, &len); - if (stu__tok == 0) - return; - switch(stu__tok) { - case ST_white : stu__curbuf += len; goto retry; - case T__none : stu__tok = *stu__curbuf; break; - case ST_string: stu__tokval = make_string(stu__curbuf+1, len-2); break; - case ST_id : stu__tokval = make_string(stu__curbuf, len); break; - case ST_hex : stu__tokval = stu__makeint(strtol(stu__curbuf+2,NULL,16)); stu__tok = ST_number; break; - case ST_decimal: stu__tokval = stu__makeint(strtol(stu__curbuf ,NULL,10)); stu__tok = ST_number; break; - case ST_float : stu__tokval = stua_float((float) atof(stu__curbuf)) ; stu__tok = ST_number; break; - case ST_char : stu__tokval = stu__curbuf[2] == '\\' ? stu__curbuf[3] : stu__curbuf[2]; - if (stu__curbuf[3] == 't') stu__tokval = '\t'; - if (stu__curbuf[3] == 'n') stu__tokval = '\n'; - if (stu__curbuf[3] == 'r') stu__tokval = '\r'; - stu__tokval = stu__makeint(stu__tokval); - stu__tok = ST_number; - break; - } - stu__curbuf += len; -} - -static struct { int stu__tok; char *regex; } stu__lexemes[] = -{ - ST_white , "([ \t\n\r]|/\\*(.|\n)*\\*/|//[^\r\n]*([\r\n]|$))+", - ST_id , "[_a-zA-Z][_a-zA-Z0-9]*", - ST_hex , "0x[0-9a-fA-F]+", - ST_decimal, "[0-9]+[0-9]*", - ST_float , "[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?", - ST_float , "\\.[0-9]+([eE][-+]?[0-9]+)?", - ST_char , "c'(\\\\.|[^\\'])'", - ST_string , "\"(\\\\.|[^\\\"\n\r])*\"", - ST_string , "\'(\\\\.|[^\\\'\n\r])*\'", - - #define stua_key4(a,b,c,d) ST_##a, #a, ST_##b, #b, ST_##c, #c, ST_##d, #d, - stua_key4(if,then,else,elseif) stua_key4(while,do,for,in) - stua_key4(func,var,let,break) stua_key4(nil,true,false,end) - stua_key4(return,continue,as,repeat) stua_key4(_frame,catch,catch,catch) - - ST_shl, "<<", ST_and, "&&", ST_eq, "==", ST_ge, ">=", - ST_shr, ">>", ST_or , "||", ST_ne, "!=", ST_le, "<=", - ST_shru,">>>", ST_into, "=>", - T__none, ".", -}; - -typedef struct -{ - stua_obj *data; // constants being compiled - short *code; // code being compiled - stua_dict *locals; - short *non_local_refs; -} stu__comp_func; - -static stu__comp_func stu__pfunc; -static stu__comp_func *func_stack = NULL; -static void stu__push_func_comp(void) -{ - stb_arr_push(func_stack, stu__pfunc); - stu__pfunc.data = NULL; - stu__pfunc.code = NULL; - stu__pfunc.locals = stb_idict_new_size(16); - stu__pfunc.non_local_refs = NULL; - stb_arr_push(stu__pfunc.code, 0); // number of data items - stb_arr_push(stu__pfunc.code, 1); // starting execution address -} - -static void stu__pop_func_comp(void) -{ - stb_arr_free(stu__pfunc.code); - stb_arr_free(stu__pfunc.data); - stb_idict_destroy(stu__pfunc.locals); - stb_arr_free(stu__pfunc.non_local_refs); - stu__pfunc = stb_arr_pop(func_stack); -} - -// if an id is a reference to an outer lexical scope, this -// function returns the "name" of it, and updates the stack -// structures to make sure the names are propagated in. -static int stu__nonlocal_id(stua_obj var_obj) -{ - stua_obj dummy, var = var_obj; - int i, n = stb_arr_len(func_stack), j,k; - if (stb_idict_get_flag(stu__pfunc.locals, var, &dummy)) return 0; - for (i=n-1; i > 1; --i) { - if (stb_idict_get_flag(func_stack[i].locals, var, &dummy)) - break; - } - if (i <= 1) return 0; // stu__compile_global_scope - j = i; // need to access variable from j'th frame - for (i=0; i < stb_arr_len(stu__pfunc.non_local_refs); ++i) - if (stu__pfunc.non_local_refs[i] == j) return j-n; - stb_arr_push(stu__pfunc.non_local_refs, j-n); - // now make sure all the parents propagate it down - for (k=n-1; k > 1; --k) { - if (j-k >= 0) return j-n; // comes direct from this parent - for(i=0; i < stb_arr_len(func_stack[k].non_local_refs); ++i) - if (func_stack[k].non_local_refs[i] == j-k) - return j-n; - stb_arr_push(func_stack[k].non_local_refs, j-k); - } - assert (k != 1); - - return j-n; -} - -static int stu__off(void) { return stb_arr_len(stu__pfunc.code); } -static void stu__cc(int a) -{ - assert(a >= -2000 && a < 5000); - stb_arr_push(stu__pfunc.code, a); -} -static int stu__cc1(int a) { stu__cc(a); return stu__off()-1; } -static int stu__cc2(int a, int b) { stu__cc(a); stu__cc(b); return stu__off()-2; } -static int stu__cc3(int a, int b, int c) { - if (a == '=') assert(c != 0); - stu__cc(a); stu__cc(b); stu__cc(c); return stu__off()-3; } -static int stu__cc4(int a, int b, int c, int d) { stu__cc(a); stu__cc(b); stu__cc(c); stu__cc(d); return stu__off()-4; } - -static int stu__cdv(stua_obj p) -{ - int i; - assert(p != STUA_NO_VALUE); - for (i=0; i < stb_arr_len(stu__pfunc.data); ++i) - if (stu__pfunc.data[i] == p) - break; - if (i == stb_arr_len(stu__pfunc.data)) - stb_arr_push(stu__pfunc.data, p); - return ~i; -} - -static int stu__cdt(void) -{ - int z = stu__cdv(stu__tokval); - stu__nexttoken(); - return z; -} - -static int stu__seq(int a, int b) -{ - return !a ? b : !b ? a : stu__cc3(STU__seq, a,b); -} - -static char stu__comp_err_str[1024]; -static int stu__comp_err_line; -static int stu__err(char *str, ...) -{ - va_list v; - char *s = stu__bufstart; - stu__comp_err_line = 1; - while (s < stu__curbuf) { - if (s[0] == '\n' || s[0] == '\r') { - if (s[0]+s[1] == '\n' + '\r') ++s; - ++stu__comp_err_line; - } - ++s; - } - va_start(v, str); - vsprintf(stu__comp_err_str, str, v); - va_end(v); - return 0; -} - -static int stu__accept(int p) -{ - if (stu__tok != p) return 0; - stu__nexttoken(); - return 1; -} - -static int stu__demand(int p) -{ - if (stu__accept(p)) return 1; - return stu__err("Didn't find expected stu__tok"); -} - -static int stu__demandv(int p, stua_obj *val) -{ - if (stu__tok == p || p==0) { - *val = stu__tokval; - stu__nexttoken(); - return 1; - } else - return 0; -} - -static int stu__expr(int p); -int stu__nexpr(int p) { stu__nexttoken(); return stu__expr(p); } -static int stu__statements(int once, int as); - -static int stu__parse_if(void) // parse both ST_if and ST_elseif -{ - int b,c,a; - a = stu__nexpr(1); if (!a) return 0; - if (!stu__demand(ST_then)) return stu__err("expecting THEN"); - b = stu__statements(0,0); if (!b) return 0; - if (b == 1) b = -1; - - if (stu__tok == ST_elseif) { - return stu__parse_if(); - } else if (stu__accept(ST_else)) { - c = stu__statements(0,0); if (!c) return 0; - if (!stu__demand(ST_end)) return stu__err("expecting END after else clause"); - return stu__cc4(ST_else, a, b, c); - } else { - if (!stu__demand(ST_end)) return stu__err("expecting END in if statement"); - return stu__cc3(ST_if, a, b); - } -} - -int stu__varinit(int z, int in_globals) -{ - int a,b; - stu__nexttoken(); - while (stu__demandv(ST_id, &b)) { - if (!stb_idict_add(stu__pfunc.locals, b, 1)) - if (!in_globals) return stu__err("Redefined variable %s.", stu__pw(b)->ptr); - if (stu__accept('=')) { - a = stu__expr(1); if (!a) return 0; - } else - a = stu__cdv(stua_nil); - z = stu__seq(z, stu__cc3(ST_var, stu__cdv(b), a)); - if (!stu__accept(',')) break; - } - return z; -} - -static int stu__compile_unary(int z, int outparm, int require_inparm) -{ - int op = stu__tok, a, b; - stu__nexttoken(); - if (outparm) { - if (require_inparm || (stu__tok && stu__tok != ST_end && stu__tok != ST_else && stu__tok != ST_elseif && stu__tok !=';')) { - a = stu__expr(1); if (!a) return 0; - } else - a = stu__cdv(stua_nil); - b = stu__cc2(op, a); - } else - b = stu__cc1(op); - return stu__seq(z,b); -} - -static int stu__assign(void) -{ - int z; - stu__accept(ST_let); - z = stu__expr(1); if (!z) return 0; - if (stu__accept('=')) { - int y,p = (z >= 0 ? stu__pfunc.code[z] : 0); - if (z < 0 || (p != ST_id && p != '[')) return stu__err("Invalid lvalue in assignment"); - y = stu__assign(); if (!y) return 0; - z = stu__cc3('=', z, y); - } - return z; -} - -static int stu__statements(int once, int stop_while) -{ - int a,b, c, z=0; - for(;;) { - switch (stu__tok) { - case ST_if : a = stu__parse_if(); if (!a) return 0; - z = stu__seq(z, a); - break; - case ST_while : if (stop_while) return (z ? z:1); - a = stu__nexpr(1); if (!a) return 0; - if (stu__accept(ST_as)) c = stu__statements(0,0); else c = 0; - if (!stu__demand(ST_do)) return stu__err("expecting DO"); - b = stu__statements(0,0); if (!b) return 0; - if (!stu__demand(ST_end)) return stu__err("expecting END"); - if (b == 1) b = -1; - z = stu__seq(z, stu__cc4(ST_while, a, b, c)); - break; - case ST_repeat : stu__nexttoken(); - c = stu__statements(0,1); if (!c) return 0; - if (!stu__demand(ST_while)) return stu__err("expecting WHILE"); - a = stu__expr(1); if (!a) return 0; - if (!stu__demand(ST_do)) return stu__err("expecting DO"); - b = stu__statements(0,0); if (!b) return 0; - if (!stu__demand(ST_end)) return stu__err("expecting END"); - if (b == 1) b = -1; - z = stu__seq(z, stu__cc4(ST_as, a, b, c)); - break; - case ST_catch : a = stu__nexpr(1); if (!a) return 0; - z = stu__seq(z, stu__cc2(ST_catch, a)); - break; - case ST_var : z = stu__varinit(z,0); break; - case ST_return : z = stu__compile_unary(z,1,1); break; - case ST_continue:z = stu__compile_unary(z,0,0); break; - case ST_break : z = stu__compile_unary(z,1,0); break; - case ST_into : if (z == 0 && !once) return stu__err("=> cannot be first statement in block"); - a = stu__nexpr(99); - b = (a >= 0? stu__pfunc.code[a] : 0); - if (a < 0 || (b != ST_id && b != '[')) return stu__err("Invalid lvalue on right side of =>"); - z = stu__cc3('=', a, z); - break; - default : if (stu__end[stu__tok]) return once ? 0 : (z ? z:1); - a = stu__assign(); if (!a) return 0; - stu__accept(';'); - if (stu__tok && !stu__end[stu__tok]) { - if (a < 0) - return stu__err("Constant has no effect"); - if (stu__pfunc.code[a] != '(' && stu__pfunc.code[a] != '=') - return stu__err("Expression has no effect"); - } - z = stu__seq(z, a); - break; - } - if (!z) return 0; - stu__accept(';'); - if (once && stu__tok != ST_into) return z; - } -} - -static int stu__postexpr(int z, int p); -static int stu__dictdef(int end, int *count) -{ - int z,n=0,i,flags=0; - short *dict=NULL; - stu__nexttoken(); - while (stu__tok != end) { - if (stu__tok == ST_id) { - stua_obj id = stu__tokval; - stu__nexttoken(); - if (stu__tok == '=') { - flags |= 1; - stb_arr_push(dict, stu__cdv(id)); - z = stu__nexpr(1); if (!z) return 0; - } else { - z = stu__cc2(ST_id, stu__cdv(id)); - z = stu__postexpr(z,1); if (!z) return 0; - flags |= 2; - stb_arr_push(dict, stu__cdv(stu__makeint(n++))); - } - } else { - z = stu__expr(1); if (!z) return 0; - flags |= 2; - stb_arr_push(dict, stu__cdv(stu__makeint(n++))); - } - if (end != ')' && flags == 3) { z=stu__err("can't mix initialized and uninitialized defs"); goto done;} - stb_arr_push(dict, z); - if (!stu__accept(',')) break; - } - if (!stu__demand(end)) - return stu__err(end == ')' ? "Expecting ) at end of function call" - : "Expecting } at end of dictionary definition"); - z = stu__cc2('{', stb_arr_len(dict)/2); - for (i=0; i < stb_arr_len(dict); ++i) - stu__cc(dict[i]); - if (count) *count = n; -done: - stb_arr_free(dict); - return z; -} - -static int stu__comp_id(void) -{ - int z,d; - d = stu__nonlocal_id(stu__tokval); - if (d == 0) - return z = stu__cc2(ST_id, stu__cdt()); - // access a non-local frame by naming it with the appropriate int - assert(d < 0); - z = stu__cdv(d); // relative frame # is the 'variable' in our local frame - z = stu__cc2(ST_id, z); // now access that dictionary - return stu__cc3('[', z, stu__cdt()); // now access the variable from that dir -} - -static stua_obj stu__funcdef(stua_obj *id, stua_obj *func); -static int stu__expr(int p) -{ - int z; - // unary - switch (stu__tok) { - case ST_number: z = stu__cdt(); break; - case ST_string: z = stu__cdt(); break; // @TODO - string concatenation like C - case ST_id : z = stu__comp_id(); break; - case ST__frame: z = stu__cc1(ST__frame); stu__nexttoken(); break; - case ST_func : z = stu__funcdef(NULL,NULL); break; - case ST_if : z = stu__parse_if(); break; - case ST_nil : z = stu__cdv(stua_nil); stu__nexttoken(); break; - case ST_true : z = stu__cdv(stua_true); stu__nexttoken(); break; - case ST_false : z = stu__cdv(stua_false); stu__nexttoken(); break; - case '-' : z = stu__nexpr(99); if (z) z=stu__cc2(STU__negate,z); else return z; break; - case '!' : z = stu__nexpr(99); if (z) z=stu__cc2('!',z); else return z; break; - case '~' : z = stu__nexpr(99); if (z) z=stu__cc2('~',z); else return z; break; - case '{' : z = stu__dictdef('}', NULL); break; - default : return stu__err("Unexpected token"); - case '(' : stu__nexttoken(); z = stu__statements(0,0); if (!stu__demand(')')) return stu__err("Expecting )"); - } - return stu__postexpr(z,p); -} - -static int stu__postexpr(int z, int p) -{ - int q; - // postfix - while (stu__tok == '(' || stu__tok == '[' || stu__tok == '.') { - if (stu__accept('.')) { - // MUST be followed by a plain identifier! use [] for other stuff - if (stu__tok != ST_id) return stu__err("Must follow . with plain name; try [] instead"); - z = stu__cc3('[', z, stu__cdv(stu__tokval)); - stu__nexttoken(); - } else if (stu__accept('[')) { - while (stu__tok != ']') { - int r = stu__expr(1); if (!r) return 0; - z = stu__cc3('[', z, r); - if (!stu__accept(',')) break; - } - if (!stu__demand(']')) return stu__err("Expecting ]"); - } else { - int n, p = stu__dictdef(')', &n); if (!p) return 0; - #if 0 // this is incorrect! - if (z > 0 && stu__pfunc.code[z] == ST_id) { - stua_obj q = stu__get(stu__globaldict, stu__pfunc.data[-stu__pfunc.code[z+1]-1], stua_nil); - if (stu__checkt(STU___function, q)) - if ((stu__pf(q))->num_param != n) - return stu__err("Incorrect number of parameters"); - } - #endif - z = stu__cc3('(', z, p); - } - } - // binop - this implementation taken from lcc - for (q=stu__prec[stu__tok]; q >= p; --q) { - while (stu__prec[stu__tok] == q) { - int o = stu__tok, y = stu__nexpr(p+1); if (!y) return 0; - z = stu__cc3(o,z,y); - } - } - return z; -} - -static stua_obj stu__finish_func(stua_obj *param, int start) -{ - int n, size; - stu__func *f = (stu__func *) malloc(sizeof(*f)); - f->closure_source = 0; - f->num_param = stb_arr_len(param); - f->param = (int *) stb_copy(param, f->num_param * sizeof(*f->param)); - size = stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data) + sizeof(*f) + 8; - f->f.store = malloc(stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data)); - f->code = (short *) ((char *) f->f.store + stb_arr_storage(stu__pfunc.data)); - memcpy(f->code, stu__pfunc.code, stb_arr_storage(stu__pfunc.code)); - f->code[1] = start; - f->code[0] = stb_arr_len(stu__pfunc.data); - for (n=0; n < f->code[0]; ++n) - ((stua_obj *) f->code)[-1-n] = stu__pfunc.data[n]; - return stu__makeobj(STU___function, f, size, 0); -} - -static int stu__funcdef(stua_obj *id, stua_obj *result) -{ - int n,z=0,i,q; - stua_obj *param = NULL; - short *nonlocal; - stua_obj v,f=stua_nil; - assert(stu__tok == ST_func); - stu__nexttoken(); - if (id) { - if (!stu__demandv(ST_id, id)) return stu__err("Expecting function name"); - } else - stu__accept(ST_id); - if (!stu__demand('(')) return stu__err("Expecting ( for function parameter"); - stu__push_func_comp(); - while (stu__tok != ')') { - if (!stu__demandv(ST_id, &v)) { z=stu__err("Expecting parameter name"); goto done; } - stb_idict_add(stu__pfunc.locals, v, 1); - if (stu__tok == '=') { - n = stu__nexpr(1); if (!n) { z=0; goto done; } - z = stu__seq(z, stu__cc3(STU__defaultparm, stu__cdv(v), n)); - } else - stb_arr_push(param, v); - if (!stu__accept(',')) break; - } - if (!stu__demand(')')) { z=stu__err("Expecting ) at end of parameter list"); goto done; } - n = stu__statements(0,0); if (!n) { z=0; goto done; } - if (!stu__demand(ST_end)) { z=stu__err("Expecting END at end of function"); goto done; } - if (n == 1) n = 0; - n = stu__seq(z,n); - f = stu__finish_func(param, n); - if (result) { *result = f; z=1; stu__pop_func_comp(); } - else { - nonlocal = stu__pfunc.non_local_refs; - stu__pfunc.non_local_refs = NULL; - stu__pop_func_comp(); - z = stu__cdv(f); - if (nonlocal) { // build a closure with references to the needed frames - short *initcode = NULL; - for (i=0; i < stb_arr_len(nonlocal); ++i) { - int k = nonlocal[i], p; - stb_arr_push(initcode, stu__cdv(k)); - if (k == -1) p = stu__cc1(ST__frame); - else { p = stu__cdv(stu__makeint(k+1)); p = stu__cc2(ST_id, p); } - stb_arr_push(initcode, p); - } - q = stu__cc2('{', stb_arr_len(nonlocal)); - for (i=0; i < stb_arr_len(initcode); ++i) - stu__cc(initcode[i]); - z = stu__cc3('+', z, q); - stb_arr_free(initcode); - } - stb_arr_free(nonlocal); - } -done: - stb_arr_free(param); - if (!z) stu__pop_func_comp(); - return z; -} - -static int stu__compile_global_scope(void) -{ - stua_obj o; - int z=0; - - stu__push_func_comp(); - while (stu__tok != 0) { - if (stu__tok == ST_func) { - stua_obj id, f; - if (!stu__funcdef(&id,&f)) - goto error; - stu__set(stu__globaldict, id, f); - } else if (stu__tok == ST_var) { - z = stu__varinit(z,1); if (!z) goto error; - } else { - int y = stu__statements(1,0); if (!y) goto error; - z = stu__seq(z,y); - } - stu__accept(';'); - } - o = stu__finish_func(NULL, z); - stu__pop_func_comp(); - - o = stu__funceval(o, stua_globals); // initialize stu__globaldict - if (stu__flow == FLOW_error) - printf("Error: %s\n", ((stu__wrapper *) stu__ptr(stu__flow_val))->ptr); - return 1; -error: - stu__pop_func_comp(); - return 0; -} - -stua_obj stu__myprint(stua_dict *context) -{ - stua_obj x = stu__get(context, stua_string("x"), stua_nil); - if ((x & 1) == stu__float_tag) printf("%f", stu__getfloat(x)); - else if (stu__tag(x) == stu__int_tag) printf("%d", stu__int(x)); - else { - stu__wrapper *s = stu__pw(x); - if (s->type == STU___string || s->type == STU___error) - printf("%s", s->ptr); - else if (s->type == STU___dict) printf("{{dictionary}}"); - else if (s->type == STU___function) printf("[[function]]"); - else - printf("[[ERROR:%s]]", s->ptr); - } - return x; -} - -void stua_init(void) -{ - if (!stu__globaldict) { - int i; - stua_obj s; - stu__func *f; - - stu__prec[ST_and] = stu__prec[ST_or] = 1; - stu__prec[ST_eq ] = stu__prec[ST_ne] = stu__prec[ST_le] = - stu__prec[ST_ge] = stu__prec['>' ] = stu__prec['<'] = 2; - stu__prec[':'] = 3; - stu__prec['&'] = stu__prec['|'] = stu__prec['^'] = 4; - stu__prec['+'] = stu__prec['-'] = 5; - stu__prec['*'] = stu__prec['/'] = stu__prec['%'] = - stu__prec[ST_shl]= stu__prec[ST_shr]= stu__prec[ST_shru]= 6; - - stu__end[')'] = stu__end[ST_end] = stu__end[ST_else] = 1; - stu__end[ST_do] = stu__end[ST_elseif] = 1; - - stu__float_init(); - stu__lex_matcher = stb_lex_matcher(); - for (i=0; i < sizeof(stu__lexemes)/sizeof(stu__lexemes[0]); ++i) - stb_lex_item(stu__lex_matcher, stu__lexemes[i].regex, stu__lexemes[i].stu__tok); - - stu__globaldict = stb_idict_new_size(64); - stua_globals = stu__makeobj(STU___dict, stu__globaldict, 0,0); - stu__strings = stb_sdict_new(0); - - stu__curbuf = stu__bufstart = "func _print(x) end\n" - "func print()\n var x=0 while _frame[x] != nil as x=x+1 do _print(_frame[x]) end end\n"; - stu__nexttoken(); - if (!stu__compile_global_scope()) - printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str); - - s = stu__get(stu__globaldict, stua_string("_print"), stua_nil); - if (stu__tag(s) == stu__ptr_tag && stu__ptr(s)->type == STU___function) { - f = stu__pf(s); - free(f->f.store); - f->closure_source = 4; - f->f.func = stu__myprint; - f->code = NULL; - } - } -} - -void stua_uninit(void) -{ - if (stu__globaldict) { - stb_idict_remove_all(stu__globaldict); - stb_arr_setlen(stu__gc_root_stack, 0); - stua_gc(1); - stb_idict_destroy(stu__globaldict); - stb_sdict_delete(stu__strings); - stb_matcher_free(stu__lex_matcher); - stb_arr_free(stu__gc_ptrlist); - stb_arr_free(func_stack); - stb_arr_free(stu__gc_root_stack); - stu__globaldict = NULL; - } -} - -void stua_run_script(char *s) -{ - stua_init(); - - stu__curbuf = stu__bufstart = s; - stu__nexttoken(); - - stu__flow = FLOW_normal; - - if (!stu__compile_global_scope()) - printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str); - stua_gc(1); -} -#endif // STB_DEFINE -#endif // STB_STUA - #undef STB_EXTERN #endif // STB_INCLUDE_STB_H From ab18d9b250494249a433068cc3583129d809b322 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 21:42:44 -0700 Subject: [PATCH 56/76] stb_image: Fix two bugs found via VC++ /analyze Also fixes issue #366. --- stb_image.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index f2e3430..e68580f 100644 --- a/stb_image.h +++ b/stb_image.h @@ -3821,6 +3821,10 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp else decode_n = z->s->img_n; + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + // resample and color-convert { int k; @@ -6862,9 +6866,10 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, } if (delays) { - *delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); - if (!*delays) + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; delays_size = layers * sizeof(int); } } else { From 17bc84e15dfb7c5c7ebcc5246e929678478b15a4 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 21:47:13 -0700 Subject: [PATCH 57/76] stb_image: stbi__bmp_info only rewind stream on error To be consistent with the other info functions. Fixes issue #892. --- stb_image.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index e68580f..32d5e88 100644 --- a/stb_image.h +++ b/stb_image.h @@ -7205,9 +7205,10 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) info.all_a = 255; p = stbi__bmp_parse_header(s, &info); - stbi__rewind( s ); - if (p == NULL) + if (p == NULL) { + stbi__rewind( s ); return 0; + } if (x) *x = s->img_x; if (y) *y = s->img_y; if (comp) { From 1e82fd4a4ebe9ccc70dd86776a47a24ff02769fd Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Sun, 4 Jul 2021 22:17:57 -0700 Subject: [PATCH 58/76] stb_image: BMP v4/v5 header parsing fixes As per MS's own docs, should ignore the r/g/b bitmasks in the header unless BI_BITFIELDS compression is selected. Factor out setting the default masks since that now exists in two branches. Add some more checking for unsupported compression formats and illegal bpp/compression combinations while I'm at it. Fixes issue #783. --- stb_image.h | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/stb_image.h b/stb_image.h index 32d5e88..4f684e3 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5320,6 +5320,32 @@ typedef struct int extra_read; } stbi__bmp_data; +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) { int hsz; @@ -5347,6 +5373,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) if (hsz != 12) { int compress = stbi__get32le(s); if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel stbi__get32le(s); // discard sizeof stbi__get32le(s); // discard hres stbi__get32le(s); // discard vres @@ -5361,17 +5389,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) } if (info->bpp == 16 || info->bpp == 32) { if (compress == 0) { - if (info->bpp == 32) { - info->mr = 0xffu << 16; - info->mg = 0xffu << 8; - info->mb = 0xffu << 0; - info->ma = 0xffu << 24; - info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 - } else { - info->mr = 31u << 10; - info->mg = 31u << 5; - info->mb = 31u << 0; - } + stbi__bmp_set_mask_defaults(info, compress); } else if (compress == 3) { info->mr = stbi__get32le(s); info->mg = stbi__get32le(s); @@ -5386,6 +5404,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) return stbi__errpuc("bad BMP", "bad BMP"); } } else { + // V4/V5 header int i; if (hsz != 108 && hsz != 124) return stbi__errpuc("bad BMP", "bad BMP"); @@ -5393,6 +5412,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) info->mg = stbi__get32le(s); info->mb = stbi__get32le(s); info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); stbi__get32le(s); // discard color space for (i=0; i < 12; ++i) stbi__get32le(s); // discard color space parameters From a5d989c358a47e1f0245e11040904a9d7fbf9786 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 20:07:12 -0700 Subject: [PATCH 59/76] stb_truetype: Tabs->spaces Whitespace only. --- stb_truetype.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index e06b867..8a704b6 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -4489,32 +4489,32 @@ static float stbtt__cuberoot( float x ) // x^3 + c*x^2 + b*x + a = 0 static int stbtt__solve_cubic(float a, float b, float c, float* r) { - float s = -a / 3; - float p = b - a*a / 3; - float q = a * (2*a*a - 9*b) / 27 + c; + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; float p3 = p*p*p; - float d = q*q + 4*p3 / 27; - if (d >= 0) { - float z = (float) STBTT_sqrt(d); - float u = (-q + z) / 2; - float v = (-q - z) / 2; - u = stbtt__cuberoot(u); - v = stbtt__cuberoot(v); - r[0] = s + u + v; - return 1; - } else { - float u = (float) STBTT_sqrt(-p/3); - float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative - float m = (float) STBTT_cos(v); + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; - r[0] = s + u * 2 * m; - r[1] = s - u * (m + n); - r[2] = s - u * (m - n); + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); - return 3; + return 3; } } From ba5cc43d33fd06875c254d46a301ec188aa441a7 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 20:10:22 -0700 Subject: [PATCH 60/76] stb_truetype: Fix stbtt__solve_cubic comment --- stb_truetype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_truetype.h b/stb_truetype.h index 8a704b6..a58fc62 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -4486,7 +4486,7 @@ static float stbtt__cuberoot( float x ) return (float) STBTT_pow( x,1.0f/3.0f); } -// x^3 + c*x^2 + b*x + a = 0 +// x^3 + a*x^2 + b*x + c = 0 static int stbtt__solve_cubic(float a, float b, float c, float* r) { float s = -a / 3; From e817b4a998abdd7dfdacab5d76384b310f54f4f0 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 20:17:12 -0700 Subject: [PATCH 61/76] stb_ds: Fix typos in docs. --- stb_ds.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_ds.h b/stb_ds.h index cf6be15..c74164e 100644 --- a/stb_ds.h +++ b/stb_ds.h @@ -104,7 +104,7 @@ DOCUMENTATION moving the rest of the array over. Returns b. arrinsn: - void arrins(T* a, int p, int n); + void arrinsn(T* a, int p, int n); Inserts n uninitialized items into array a starting at a[p], moving the rest of the array over. @@ -123,7 +123,7 @@ DOCUMENTATION Deletes the element at a[p], moving the rest of the array over. arrdeln: - void arrdel(T* a, int p, int n); + void arrdeln(T* a, int p, int n); Deletes n elements starting at a[p], moving the rest of the array over. arrdelswap: From 76a0a00874a5075bf590d1fd2f40de1836aea567 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 20:19:51 -0700 Subject: [PATCH 62/76] stb.h: _MSC_VER in readdir_raw -> _WIN32 For MinGW. --- deprecated/stb.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/deprecated/stb.h b/deprecated/stb.h index cd715e7..0a5fd55 100644 --- a/deprecated/stb.h +++ b/deprecated/stb.h @@ -6132,7 +6132,7 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) char buffer[4096], with_slash[4096]; size_t n; - #ifdef _MSC_VER + #ifdef WIN32 stb__wchar *ws; struct _wfinddata_t data; #ifdef _WIN64 @@ -6142,7 +6142,7 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) const long none = -1; long z; #endif - #else // !_MSC_VER + #else // !WIN32 const DIR *none = NULL; DIR *z; #endif @@ -6159,7 +6159,7 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) if (!stb_strscpy(with_slash,buffer,sizeof(with_slash))) return NULL; - #ifdef _MSC_VER + #ifdef WIN32 if (!stb_strscpy(buffer+n,"*.*",sizeof(buffer)-n)) return NULL; ws = stb__from_utf8(buffer); @@ -6170,7 +6170,7 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) if (z != none) { int nonempty = STB_TRUE; - #ifndef _MSC_VER + #ifndef WIN32 struct dirent *data = readdir(z); nonempty = (data != NULL); #endif @@ -6179,7 +6179,7 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) do { int is_subdir; - #ifdef _MSC_VER + #ifdef WIN32 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"); @@ -6207,13 +6207,13 @@ static char **readdir_raw(char *dir, int return_subdirs, char *mask) } } } - #ifdef _MSC_VER + #ifdef WIN32 while (0 == _wfindnext(z, &data)); #else while ((data = readdir(z)) != NULL); #endif } - #ifdef _MSC_VER + #ifdef WIN32 _findclose(z); #else closedir(z); From 85bc8060be3f517477f2e785c31851c6214376f2 Mon Sep 17 00:00:00 2001 From: Louis Schnellbach Date: Thu, 19 Nov 2020 15:59:51 +0100 Subject: [PATCH 63/76] Support for Page Up/Down (changes from ocornut/imgui/commit/ec945f44) --- stb_textedit.h | 71 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 41afb9e..54f4b16 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -142,6 +142,8 @@ // STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right // STB_TEXTEDIT_K_UP keyboard input to move cursor up // STB_TEXTEDIT_K_DOWN keyboard input to move cursor down +// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page +// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page // STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME // STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END // STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME @@ -164,10 +166,6 @@ // STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text // STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text // -// Todo: -// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page -// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page -// // Keyboard input must be encoded as a single integer value; e.g. a character code // and some bitflags that represent shift states. to simplify the interface, SHIFT must // be a bitflag, so we can test the shifted state of cursor movements to allow selection, @@ -331,6 +329,10 @@ typedef struct // each textfield keeps its own insert mode state. to keep an app-wide // insert mode, copy this value in/out of the app state + int row_count_per_page; + // page size in number of row. + // this value MUST be set to >0 for pageup or pagedown in multilines documents. + ///////////////////// // // private data @@ -849,12 +851,16 @@ retry: break; case STB_TEXTEDIT_K_DOWN: - case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: { + case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_PGDOWN: + case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: { StbFindState find; StbTexteditRow row; - int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN; + int row_count = is_page ? state->row_count_per_page : 1; - if (state->single_line) { + if (!is_page && state->single_line) { // on windows, up&down in single-line behave like left&right key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); goto retry; @@ -863,17 +869,20 @@ retry: if (sel) stb_textedit_prep_selection_at_cursor(state); else if (STB_TEXT_HAS_SELECTION(state)) - stb_textedit_move_to_last(str,state); + stb_textedit_move_to_last(str, state); // compute current position of cursor point stb_textedit_clamp(str, state); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - // now find character position down a row - if (find.length) { - float goal_x = state->has_preferred_x ? state->preferred_x : find.x; - float x; + for (j = 0; j < row_count; ++j) { + float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; int start = find.first_char + find.length; + + if (find.length == 0) + break; + + // now find character position down a row state->cursor = start; STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); x = row.x0; @@ -895,17 +904,25 @@ retry: if (sel) state->select_end = state->cursor; + + // go to next line + find.first_char = find.first_char + find.length; + find.length = row.num_chars; } break; } case STB_TEXTEDIT_K_UP: - case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: { + case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: + case STB_TEXTEDIT_K_PGUP: + case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: { StbFindState find; StbTexteditRow row; - int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; + int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP; + int row_count = is_page ? state->row_count_per_page : 1; - if (state->single_line) { + if (!is_page && state->single_line) { // on windows, up&down become left&right key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); goto retry; @@ -920,11 +937,14 @@ retry: stb_textedit_clamp(str, state); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); - // can only go up if there's a previous row - if (find.prev_first != find.first_char) { + for (j = 0; j < row_count; ++j) { + float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; + + // can only go up if there's a previous row + if (find.prev_first == find.first_char) + break; + // now find character position up a row - float goal_x = state->has_preferred_x ? state->preferred_x : find.x; - float x; state->cursor = find.prev_first; STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); x = row.x0; @@ -946,6 +966,14 @@ retry: if (sel) state->select_end = state->cursor; + + // go to previous line + // (we need to scan previous line the hard way. maybe we could expose this as a new API function?) + prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0; + while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE) + --prev_scan; + find.first_char = find.prev_first; + find.prev_first = prev_scan; } break; } @@ -1069,10 +1097,6 @@ retry: state->has_preferred_x = 0; break; } - -// @TODO: -// STB_TEXTEDIT_K_PGUP - move cursor up a page -// STB_TEXTEDIT_K_PGDOWN - move cursor down a page } } @@ -1337,6 +1361,7 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin state->initialized = 1; state->single_line = (unsigned char) is_single_line; state->insert_mode = 0; + state->row_count_per_page = 0; } // API initialize From eb677dda6e6a495c903cd5428ec7ebc840674f49 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 20:25:16 -0700 Subject: [PATCH 64/76] stb_textedit: Update credit, version history --- stb_textedit.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_textedit.h b/stb_textedit.h index 54f4b16..90543b0 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// stb_textedit.h - v1.13 - public domain - Sean Barrett +// stb_textedit.h - v1.14 - 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.14 ( ) page up/down, various fixes // 1.13 (2019-02-07) fix bug in undo size management // 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 @@ -52,6 +53,7 @@ // Ulf Winklemann: move-by-word in 1.1 // Fabian Giesen: secondary key inputs in 1.5 // Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 +// Louis Schnellbach: page up/down in 1.14 // // Bugfixes: // Scott Graham From 44f046af0c6f1d79ef6f189d69ac670bbfba4ac4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 5 Jul 2021 17:22:24 +0200 Subject: [PATCH 65/76] stb_textedit: Fix paste failure handling breaking undo stack Could lead to freezes. Fixes issue #734. --- stb_textedit.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stb_textedit.h b/stb_textedit.h index 90543b0..5bb3a57 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -712,9 +712,7 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta state->has_preferred_x = 0; return 1; } - // remove the undo since we didn't actually insert the characters - if (state->undostate.undo_point) - --state->undostate.undo_point; + // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) return 0; } From b691fc430594cbe3a99b32e53bf8a20decc89d97 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 20:39:35 -0700 Subject: [PATCH 66/76] stb_truetype: Remove dead assignments Confirmed from the OpenType spec that there's nothing missing here. (These were just annotations listing the total sizes of the tables, but this is not used for anything here.) Fixes issue #704. --- stb_truetype.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index a58fc62..c3c4f8e 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -2454,8 +2454,6 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); - - classDefTable = classDef1ValueArray + 2 * glyphCount; } break; case 2: { @@ -2478,8 +2476,6 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) else return (stbtt_int32)ttUSHORT(classRangeRecord + 4); } - - classDefTable = classRangeRecords + 6 * classRangeCount; } break; default: { From 2c8cd33e2eb331f94c27c0cbe79694216f434339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 6 Apr 2020 18:06:34 +0200 Subject: [PATCH 67/76] stb_image: make unpremultiply and de-iPhone flags thread_local. Follows the change done for vertical flipping in eb48fbdcede98f93dab3a5e42ce5b0072b739cf1 for these two options as well. --- stb_image.h | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index 4f684e3..50c263c 100644 --- a/stb_image.h +++ b/stb_image.h @@ -518,6 +518,8 @@ STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); // as above, but only applies to images loaded on the thread that calls the function // this function is only available if your compiler supports thread-local variables; // calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); // ZLIB client - used by PNG, available for other purposes @@ -4927,19 +4929,46 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int return 1; } -static int stbi__unpremultiply_on_load = 0; -static int stbi__de_iphone_flag = 0; +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) { - stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; } STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) { - stbi__de_iphone_flag = flag_true_if_should_convert; + stbi__de_iphone_flag_global = flag_true_if_should_convert; } +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + static void stbi__de_iphone(stbi__png *z) { stbi__context *s = z->s; From 7e10880f53572ad2c1a949a9311f813a41bedbdd Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 20:47:30 -0700 Subject: [PATCH 68/76] stb_image: Update credits --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 50c263c..760dc34 100644 --- a/stb_image.h +++ b/stb_image.h @@ -111,7 +111,7 @@ RECENT REVISION HISTORY: Josh Tobin Matthew Gregan github:poppolopoppo Julian Raschke Gregory Mullen Christian Floisand github:darealshinji Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 - Brad Weinberger Matvey Cherevko [reserved] + Brad Weinberger Matvey Cherevko github:mosra Luca Sas Alexander Veselov Zack Middleton [reserved] Ryan C. Gordon [reserved] [reserved] DO NOT ADD YOUR NAME HERE From b18c989dc2c7c2d3852b819271a848d8159dc749 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Fri, 16 Apr 2021 04:21:42 -0400 Subject: [PATCH 69/76] stb_tilemap_editor: Fix variable usage --- stb_tilemap_editor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 9b77364..a89a516 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -2996,7 +2996,7 @@ static void stbte__tile_paint(stbte_tilemap *tm, int sx, int sy, int mapx, int m i = layer; if (i == tm->solo_layer || (!tm->layerinfo[i].hidden && tm->solo_layer < 0)) if (data[i] >= 0) - STBTE_DRAW_TILE(x0,y0, (unsigned short) data[i], 0, tm->props[mapy][mapx]); + STBTE_DRAW_TILE(sx,sy, (unsigned short) data[i], 0, tm->props[mapy][mapx]); } } @@ -3496,7 +3496,7 @@ static void stbte__tile_in_palette(stbte_tilemap *tm, int x, int y, int slot) switch (stbte__ui.event) { case STBTE__paint: stbte__draw_rect(x,y,x+tm->palette_spacing_x-1,y+tm->palette_spacing_x-1, STBTE_COLOR_TILEPALETTE_BACKGROUND); - STBTE_DRAW_TILE(x,y,t->id, slot == tm->cur_tile,0); + STBTE_DRAW_TILE(x,y,id, slot == tm->cur_tile,0); if (slot == tm->cur_tile) stbte__draw_frame_delayed(x-1,y-1,x+tm->palette_spacing_x,y+tm->palette_spacing_y, STBTE_COLOR_TILEPALETTE_OUTLINE); break; From 21bfcbbc3dfb3ed8a9c8f86d68de9dbb93eb5768 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 21:07:34 -0700 Subject: [PATCH 70/76] stb_tilemap_editor: Update version, credits --- stb_tilemap_editor.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index a89a516..180b5cd 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1,4 +1,4 @@ -// stb_tilemap_editor.h - v0.41 - Sean Barrett - http://nothings.org/stb +// stb_tilemap_editor.h - v0.42 - Sean Barrett - http://nothings.org/stb // placed in the public domain - not copyrighted - first released 2014-09 // // Embeddable tilemap editor for C/C++ @@ -275,6 +275,7 @@ // either approach allows cut&pasting between levels.) // // REVISION HISTORY +// 0.42 fix compilation errors // 0.41 fix warnings // 0.40 fix warning // 0.39 fix warning @@ -317,6 +318,7 @@ // Bugfixes: // Ryan Whitworth // Eugene Opalev +// Rob Loach // // LICENSE // From 77eedd4fcfb6d25eb8fd2f306384fdaf733103ad Mon Sep 17 00:00:00 2001 From: Werner Stoop Date: Fri, 9 Apr 2021 20:03:01 +0200 Subject: [PATCH 71/76] stb_tilemap_editor: Several fixes. Re-added calls to `stbte__hittest()`, fixed some compiler errors. Also fixed some GCC warnings about unused variables when STBTE__COLORPICKER and STBTE_ALLOW_LINK is not defined. --- stb_tilemap_editor.h | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 180b5cd..d5bdd81 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1823,6 +1823,8 @@ static int stbte__button(int colormode, const char *label, int x, int y, int tex int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT; int s = STBTE__BUTTON_INTERNAL_SPACING; + if(!disabled) stbte__hittest(x0,y0,x1,y1,id); + if (stbte__ui.event == STBTE__paint) stbte__draw_textbox(x0,y0,x1,y1, (char*) label,s+textoff,s, colormode, STBTE__INDEX_FOR_ID(id,disabled,toggled)); if (disabled) @@ -1835,6 +1837,8 @@ static int stbte__button_icon(int colormode, char ch, int x, int y, int width, i int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT; int s = STBTE__BUTTON_INTERNAL_SPACING; + stbte__hittest(x0,y0,x1,y1,id); + if (stbte__ui.event == STBTE__paint) { char label[2] = { ch, 0 }; int pad = (9 - stbte__get_char_width(ch))/2; @@ -1848,6 +1852,7 @@ static int stbte__button_icon(int colormode, char ch, int x, int y, int width, i 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; + stbte__hittest(x0,y0,x1,y1,id); if (stbte__ui.event == STBTE__paint) { char str[2] = { (char)ch, 0 }; stbte__draw_textbox(x0,y0,x1,y1, str,1,0,colormode, STBTE__INDEX_FOR_ID(id,0,0)); @@ -1858,6 +1863,7 @@ static int stbte__minibutton(int colormode, int x, int y, int ch, int id) static int stbte__layerbutton(int x, int y, int ch, int id, int toggled, int disabled, int colormode) { int x0 = x, y0 = y, x1 = x+10, y1 = y+11; + if(!disabled) stbte__hittest(x0,y0,x1,y1,id); if (stbte__ui.event == STBTE__paint) { char str[2] = { (char)ch, 0 }; int off = (9-stbte__get_char_width(ch))/2; @@ -1871,6 +1877,7 @@ static int stbte__layerbutton(int x, int y, int ch, int id, int toggled, int dis static int stbte__microbutton(int x, int y, int size, int id, int colormode) { int x0 = x, y0 = y, x1 = x+size, y1 = y+size; + stbte__hittest(x0,y0,x1,y1,id); if (stbte__ui.event == STBTE__paint) { stbte__draw_box(x0,y0,x1,y1, colormode, STBTE__INDEX_FOR_ID(id,0,0)); } @@ -1880,6 +1887,7 @@ static int stbte__microbutton(int x, int y, int size, int id, int colormode) static int stbte__microbutton_dragger(int x, int y, int size, int id, int *pos) { int x0 = x, y0 = y, x1 = x+size, y1 = y+size; + stbte__hittest(x0,y0,x1,y1,id); switch (stbte__ui.event) { case STBTE__paint: stbte__draw_box(x0,y0,x1,y1, STBTE__cexpander, STBTE__INDEX_FOR_ID(id,0,0)); @@ -1910,6 +1918,8 @@ static int stbte__category_button(const char *label, int x, int y, int width, in int x0=x,y0=y, x1=x+width,y1=y+STBTE__BUTTON_HEIGHT; int s = STBTE__BUTTON_INTERNAL_SPACING; + stbte__hittest(x0,y0,x1,y1,id); + if (stbte__ui.event == STBTE__paint) stbte__draw_textbox(x0,y0,x1,y1, (char*) label, s,s, STBTE__ccategory_button, STBTE__INDEX_FOR_ID(id,0,toggled)); @@ -1929,6 +1939,7 @@ static int stbte__slider(int x0, int w, int y, int range, int *value, int id) { int x1 = x0+w; int pos = *value * w / (range+1); + stbte__hittest(x0,y-2,x1,y+3,id); int event_mouse_move = STBTE__change; switch (stbte__ui.event) { case STBTE__paint: @@ -1971,6 +1982,7 @@ static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, f { int x1 = x0+w; int y1 = y0+11; + stbte__hittest(x0,y0,x1,y1,id); switch (stbte__ui.event) { case STBTE__paint: { char text[32]; @@ -1982,7 +1994,7 @@ static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, f case STBTE__rightdown: if (STBTE__IS_HOT(id) && STBTE__INACTIVE()) stbte__activate(id); - return STBTE__begin; + return STBTE__begin; break; case STBTE__leftup: case STBTE__rightup: @@ -2022,7 +2034,6 @@ static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, f static void stbte__scrollbar(int x, int y0, int y1, int *val, int v0, int v1, int num_vis, int id) { - int over; int thumbpos; if (v1 - v0 <= num_vis) return; @@ -2031,7 +2042,7 @@ static void stbte__scrollbar(int x, int y0, int y1, int *val, int v0, int v1, in thumbpos = y0+2 + (y1-y0-4) * *val / (v1 - v0 - num_vis); if (thumbpos < y0) thumbpos = y0; if (thumbpos >= y1) thumbpos = y1; - over = stbte__hittest(x-1,y0,x+2,y1,id); + stbte__hittest(x-1,y0,x+2,y1,id); switch (stbte__ui.event) { case STBTE__paint: stbte__draw_rect(x,y0,x+1,y1, stbte__color_table[STBTE__cscrollbar][STBTE__text][STBTE__idle]); @@ -2809,6 +2820,10 @@ static void stbte__drag_update(stbte_tilemap *tm, int mapx, int mapy, int copy_p int ox,oy,i,deleted=0,written=0; short temp[STBTE_MAX_LAYERS]; short *data = NULL; + + STBTE__NOTUSED(deleted); + STBTE__NOTUSED(written); + if (!stbte__ui.shift) { ox = mapx - stbte__ui.drag_x; oy = mapy - stbte__ui.drag_y; @@ -2930,6 +2945,9 @@ static void stbte__tile_paint(stbte_tilemap *tm, int sx, int sy, int mapx, int m { int i; int id = STBTE__IDMAP(mapx,mapy); + int x0=sx, y0=sy; + int x1=sx+tm->spacing_x, y1=sy+tm->spacing_y; + stbte__hittest(x0,y0,x1,y1, id); short *data = tm->data[mapy][mapx]; short temp[STBTE_MAX_LAYERS]; @@ -3494,7 +3512,10 @@ static void stbte__categories(stbte_tilemap *tm, int x0, int y0, int w, int h) static void stbte__tile_in_palette(stbte_tilemap *tm, int x, int y, int slot) { + stbte__tileinfo *t = &tm->tiles[slot]; + int x0=x, y0=y, x1 = x+tm->palette_spacing_x - 1, y1 = y+tm->palette_spacing_y; int id = STBTE__ID(STBTE__palette, slot); + stbte__hittest(x0,y0,x1,y1, id); switch (stbte__ui.event) { case STBTE__paint: stbte__draw_rect(x,y,x+tm->palette_spacing_x-1,y+tm->palette_spacing_x-1, STBTE_COLOR_TILEPALETTE_BACKGROUND); @@ -3567,6 +3588,7 @@ static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h) my = stbte__ui.select_y0; p = tm->props[my][mx]; data = tm->data[my][mx]; + STBTE__NOTUSED(data); for (i=0; i < STBTE_MAX_PROPERTIES; ++i) { unsigned int n = STBTE_PROP_TYPE(i, data, p); if (n) { @@ -3646,8 +3668,9 @@ static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h) } } -static int stbte__cp_mode, stbte__cp_aspect, stbte__cp_state, stbte__cp_index, stbte__save, stbte__cp_altered, stbte__color_copy; +static int stbte__cp_mode, stbte__cp_aspect, stbte__save, stbte__cp_altered; #ifdef STBTE__COLORPICKER +static int stbte__cp_state, stbte__cp_index, stbte__color_copy; static void stbte__dump_colorstate(void) { int i,j,k; From 15d2dc5c5159e0e48b06287d123961256ab67c27 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 21:25:41 -0700 Subject: [PATCH 72/76] stb_tilemap_editor: Update contributors --- stb_tilemap_editor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index d5bdd81..fbd3388 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -319,6 +319,7 @@ // Ryan Whitworth // Eugene Opalev // Rob Loach +// github:wernsey // // LICENSE // From 6ca560c9afba1bb850e07683988583a045c8dc78 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 6 Jul 2021 21:40:31 -0700 Subject: [PATCH 73/76] stb_image: Update documentation for de-iPhone flag It's default off, not default on. Fixes issue #651. --- stb_image.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stb_image.h b/stb_image.h index 760dc34..7f6ccf3 100644 --- a/stb_image.h +++ b/stb_image.h @@ -310,11 +310,10 @@ RECENT REVISION HISTORY: // // iPhone PNG support: // -// By default we convert iphone-formatted PNGs back to RGB, even though -// they are internally encoded differently. You can disable this conversion -// by calling stbi_convert_iphone_png_to_rgb(0), in which case -// you will always just get the native iphone "format" through (which -// is BGR stored in RGB). +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). // // Call stbi_set_unpremultiply_on_load(1) as well to force a divide per // pixel to remove any premultiplied alpha *only* if the image file explicitly From 9f985460226d7939d7fd71f81b5e38dda4b06651 Mon Sep 17 00:00:00 2001 From: Devendranath Thadi Date: Wed, 25 Nov 2020 06:48:14 +0000 Subject: [PATCH 74/76] Travis-ci: added support for ppc64le --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3b71802..c2ad947 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: C +arch: + - AMD64 + - ppc64le install: true script: - cd tests From b77192742d5ae5746131f379da8157443128be6d Mon Sep 17 00:00:00 2001 From: Randy Date: Wed, 25 Nov 2020 14:04:52 +0100 Subject: [PATCH 75/76] oss-fuzz: integrate with CIFuzz --- .github/workflows/ci-fuzz.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/ci-fuzz.yml diff --git a/.github/workflows/ci-fuzz.yml b/.github/workflows/ci-fuzz.yml new file mode 100644 index 0000000..332fca9 --- /dev/null +++ b/.github/workflows/ci-fuzz.yml @@ -0,0 +1,23 @@ +name: CIFuzz +on: [pull_request] +jobs: + Fuzzing: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'stb' + dry-run: false + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'stb' + fuzz-seconds: 900 + dry-run: false + - name: Upload Crash + uses: actions/upload-artifact@v1 + if: failure() + with: + name: artifacts + path: ./out/artifacts From dcb1116f1351bc8edad059d9ca432e8f322ba922 Mon Sep 17 00:00:00 2001 From: Randy Date: Thu, 26 Nov 2020 02:18:13 +0100 Subject: [PATCH 76/76] ossfuzz: improve code coverage fix .gif pattern matching add netpbm test images derived from the public domain pngsuite added more image types (downloaded in Dockerfile) --- tests/ossfuzz.sh | 8 ++++++-- tests/pbm/basi0g16.pgm | Bin 0 -> 2064 bytes tests/pbm/basi2c16.ppm | Bin 0 -> 6160 bytes tests/pbm/cdfn2c08.ppm | Bin 0 -> 826 bytes tests/pbm/cdun2c08.ppm | Bin 0 -> 3086 bytes tests/pbm/comment.pgm | Bin 0 -> 1083 bytes tests/pbm/ctfn0g04.pgm | Bin 0 -> 1038 bytes 7 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 tests/pbm/basi0g16.pgm create mode 100644 tests/pbm/basi2c16.ppm create mode 100644 tests/pbm/cdfn2c08.ppm create mode 100644 tests/pbm/cdun2c08.ppm create mode 100644 tests/pbm/comment.pgm create mode 100644 tests/pbm/ctfn0g04.pgm diff --git a/tests/ossfuzz.sh b/tests/ossfuzz.sh index 2af98f5..4b8fd27 100755 --- a/tests/ossfuzz.sh +++ b/tests/ossfuzz.sh @@ -17,9 +17,13 @@ cp $SRC/stb/tests/stb_png.dict $OUT/stb_png_read_fuzzer.dict tar xvzf $SRC/stb/jpg.tar.gz --directory $SRC/stb/tests tar xvzf $SRC/stb/gif.tar.gz --directory $SRC/stb/tests +unzip $SRC/stb/bmp.zip -d $SRC/stb/tests +unzip $SRC/stb/tga.zip -d $SRC/stb/tests -find $SRC/stb/tests -name "*.png" -o -name "*.jpg" -o -name ".gif" | \ - xargs zip $OUT/stbi_read_fuzzer_seed_corpus.zip +find $SRC/stb/tests -name "*.png" -o -name "*.jpg" -o -name "*.gif" \ + -o -name "*.bmp" -o -name "*.tga" -o -name "*.TGA" \ + -o -name "*.ppm" -o -name "*.pgm" \ + | xargs zip $OUT/stbi_read_fuzzer_seed_corpus.zip echo "" >> $SRC/stb/tests/gif.dict cat $SRC/stb/tests/gif.dict $SRC/stb/tests/stb_png.dict > $OUT/stbi_read_fuzzer.dict diff --git a/tests/pbm/basi0g16.pgm b/tests/pbm/basi0g16.pgm new file mode 100644 index 0000000000000000000000000000000000000000..72412431a9513fbced9f9bac62f912d2edf89aea GIT binary patch literal 2064 zcmbu=_g9Sp0EhACI8KKvD_cZX_UO9VB3t&}TefTw5fNDt*;`ij%HDf#*;_>R7GLN6 z;r;{f`#*fn^E7eTYeQz>9q7qGMlznM%waKW*vuY|aF%P_<2mp6 z#y=8uMZ1)ev}7d@g(*WtYS4g|bfOo77{vspF_)#RWh;9*#(8e=fS0`I2ht0j(-ygq zp6qy16g!ovMI&0%g+2@+m@sA#&2rYWo&B8PBDZ)%0w4LsFFn!;tyd~Cl9T)t$3a!< z(1f;hqaVW<%VcJ;fR$`yCkHvjW$y5VH+<#~UlgxHS|uBq$VEX)QjTiWqZ#e#!2m`u zjw#G$5v$q6ZVq#XtK8)oZ~4k!l5|~hS|V4n;DHyVsem8;w4fsa1QJ9j5k#?s7`70{ zQOI~u!94fql!_4 ztk_wuFj=v)P$9BnCrUxGVrPbi$cmkC^_LYpp$d={JHhHAD|UvfovhdiR12Byj$x;d z8p&*T3_IObS7y6o*y$)gneC2Yr?o1}YpSor@oDk?@Y=Bqcs6*v zxNo>6Tx(n&oL9^}P8E(f4hyD;y~B86n9&F9EVc!kjJ3zgpgYk{Xgd7sFZ}c8J2*eS zBR(zOA6`3_0nY}H7xxXfglmn@2ngn~b%`%Ah;ZPETt((><-7I4N({{c(PLe-E2q#rwl+$1>pA z;PK+V;g)c%ad~iFG50uCINmrcm?HKL~>Hh3wy8Ck{ zXXI{NJLkuD#HYpk!)wPf;Mw5u;=bXQaIJB9a9%O@I8`{_I4qbV_73BPVMZUYv)C4F zGS(g|bM2;c=e66(PS@^E(_MRII2|{<44fa|5uX;7&W0p)#f`L+v>ib?R(5KfWVA zE#4nqJC*^@29Fo_4Y!1Ajmv}cin+(B!tuso!4$D~7%vPn`hcCqwqTRb#&oqm8#`6z zY~1P2v#E@o&ZhRJJDVnRBC752a(;YAd|LdKy`R^PWx%t+GrL&oPy4`CC-oUh);|6hrbW`Sq3~CJYL*4+!C%e zE)UKt<{qaC#~X(QQ^ek3yfDn@!pX%YbKt$BX-hTf()*<-vKy+~ZW?c;m2Oir71h7lwJQ zP3OZ}+o`i_?asEWb!D2o*0rzwS~s~eYuy%iu61YawAMbDZmq-2CzC>!hx6k*;?v^& z;k9G=wI9xp$BX-hTf()*<-vKy+~ZW?c;m2Oir71h*YcPy%*$gZAC||Ron4;Fv}Ji} z-{j?Ka_xU@uT*AvI_u8m@xe~Z6K2ybPrUd{vedkCetbuKTD(8Jb}R#)4IVG<8*T~L z8kYy>6?2bMh2xFGf+=F}=GAoZnpZo8d0yS=e~+R1HK*Uh@NJpbCO3Ir+fw^^?QCV{ z)dzRZYnbgcukkY7y!MVyBN67F^W!_>)8hT%wPP9Z_fq~mUfeg_60S8a56&y*9;XV& z8;1o`%)RM)mwP+KEB^{R3`Ufc4zM6WvATt z&UCp?k!RwoFxLn>Z>FjuSwk_lBLzBll%(WlycvWV+d*{yaPSH-|JuIf@Lda6uHyh-1I?}$%}_lMVx zWx%t+UV|`!x>=Y}LVv4ozU5ZVPSBh;3bBdkyAw?fLn_`&T zl487?oMP{4&+p*(>8IB-)SIaL#JtB%{tkRcd|JFeyml-Do(&!^?i+3i*BYs1oL{#~ zZ>pZUzCoR)cfTUwde@eC^{%sF?wt=l^e)Vu?OnXu!hh%g($A_VruR;_M>Rl|jH#7M z`W^U=__TO`cZ=~Y>`f>84tz&^TD(8Jb}R#)4IVG<8`8fyzdDMlvnrjc zhHjwVX1y8umUZGV>u>!WdK!ACbTf3nRi#vG)iKof)VpX%YbKt z$BQH<&aYmszNj9fdac^0I-)zN_gn9ZzIVQLeiFSwx(B+=s!6J>>JRF2>eWgd%1!J+ zNOIqS?}$%}_lMVxWx%sRGArj-ic%s`cUPxW*HHymHB@EME!7*Zw}f%uj`*~Ae|YU!24q^`{K~J&g349ODC+m>o$5oX>8g*a zHM+OlQEr0jjjE<PAsZzFP1$I(QGT(vkh);|6hu4nGX`Ek^gHpH> ztx@wj`+05Zi4e`TGr&LDNYlSrVAx?rCudSr7o7*N#D(6774mwbJfQ8$|6vwKwPd+KOt!sBN7#U)myRBcttx zHU*lxHNk2c)MTY8MTuYOSxHo>P6^1K!B=>U z?T|)=N>5Spc`|;U=k--~rf&9|hmXyZdi++mcdNDf+U(!AuRB#NE-w~Eq1N{+_4e}l ze7@af*QzYCV!6x&2$e%>NEP1`NzVq-#wuq^6eq|h|C;pted2tfEG-#`#bDuWcscCi zF$h{gClD58)N6=`jhssqNEbO9@Ijo)k<*I$3WHDEu$8hRcjIwf;Iv~aO_?~qYS_RH zxIB0*+EY*7pd7kVGhg$Do5k=`CYWE`e^m^(QK#Zz(IsirG;>Rz3?hqU6f P(p6*|{G1ovCTHLW)Hrd7 literal 0 HcmV?d00001 diff --git a/tests/pbm/cdun2c08.ppm b/tests/pbm/cdun2c08.ppm new file mode 100644 index 0000000000000000000000000000000000000000..2d7202b89dafb02c9a57f18997a48916bec26dcd GIT binary patch literal 3086 zcmb7_+p(iC3_$&zKRVc+TKerUZ2WdiTL+V0$EW((@>eIz*a;>yJq-#O-HD|wzVOV&L&3Ew& zWA>cG6;9@NzaM|&2xs2MGQI;c=yy6fBZeK?Y>QYPLrNQ&Qh2BEOrhV(D}`ZuQZ7zf z35P0(Ibq!LAs5(Uirz8T0v{JBt-T6M=)%WrEG%ee)725;&7?Z5B z|Ht*YWKv*pj)L;d1${>zn>j+>o#8je=iwZ`ue^lH{y-Rr2VIGc7$~o(Ut5u{)RFPU zo4kI!Kfw18X@4W+i~a1OBCCKoj#hJ$WaH1>BIiqn7GZ2Rly7edt1_u8=`&p=(dJ7` zD&KAP{W&+@w3rJE9~B>eUY?5e7v}co#=94UA>&)cTe~yV{>$T#w(nwmdsdG10ZO&e ztmpMQi7Wn(i)B_MaLY)cYvm)6M{sER_hvWbN literal 0 HcmV?d00001 diff --git a/tests/pbm/comment.pgm b/tests/pbm/comment.pgm new file mode 100644 index 0000000000000000000000000000000000000000..aa9dc71887f79ac4bd39c67cf3af312b332d3cea GIT binary patch literal 1083 zcmWGAl$}0GrtzKmf9z*76`b(ESavdnOQo z@q00Mk=Q%fE>zG41e1q3kjX(^A-Y>@r5mWQQtWPk4lf-^t>vY*!Spge|d LH^^QXptU>zF1GZB literal 0 HcmV?d00001 diff --git a/tests/pbm/ctfn0g04.pgm b/tests/pbm/ctfn0g04.pgm new file mode 100644 index 0000000000000000000000000000000000000000..284f8708977d076a30ee1ac63577121f46eac71a GIT binary patch literal 1038 zcmWGA<>E3nQZP2+GBP#g`i}&Rfxra_LV+L+2+Dx~N%}vn