Merge branch 'master' into working

Conflicts:
	stb_voxel_render.h
This commit is contained in:
Sean Barrett 2015-08-01 04:02:00 -07:00
commit d821fd83f3
20 changed files with 955 additions and 151 deletions

View File

@ -1,28 +1,34 @@
<!--- THIS FILE IS AUTOMATICALLY GENERATED, DO NOT CHANGE IT BY HAND --->
stb stb
=== ===
single-file public domain libraries for C/C++ single-file public domain libraries for C/C++
library | lastest version | category | description library | lastest version | category | LoC | description
--------------------- | ---- | -------- | -------------------------------- --------------------- | ---- | -------- | --- | --------------------------------
**stb_vorbis.c** | 1.04 | audio | decode ogg vorbis files from file/memory to float/16-bit signed output **stb_vorbis.c** | 1.05 | audio | 5445 | decode ogg vorbis files from file/memory to float/16-bit signed output
**stb_image.h** | 2.03 | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **stb_image.h** | 2.06 | graphics | 6437 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
**stb_truetype.h** | 1.03 | graphics | parse, decode, and rasterize characters from truetype fonts **stb_truetype.h** | 1.06 | graphics | 2632 | parse, decode, and rasterize characters from truetype fonts
**stb_image_write.h** | 0.98 | graphics | image writing to disk: PNG, TGA, BMP **stb_image_write.h** | 0.98 | graphics | 730 | image writing to disk: PNG, TGA, BMP
**stb_image_resize.h** | 0.90 | graphics | resize images larger/smaller with good quality **stb_image_resize.h** | 0.90 | graphics | 2585 | resize images larger/smaller with good quality
**stb_rect_pack.h** | 0.05 | graphics | simple 2D rectangle packer with decent quality **stb_rect_pack.h** | 0.06 | graphics | 560 | simple 2D rectangle packer with decent quality
**stretchy_buffer.h** | 1.01 | utility | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **stretchy_buffer.h** | 1.02 | utility | 210 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++
**stb_textedit.h** | 1.5 | UI | guts of a text editor for games etc implementing them from scratch **stb_textedit.h** | 1.6 | UI | 1290 | guts of a text editor for games etc implementing them from scratch
**stb_voxel_render.h** | 0.80 | 3D&nbsp;graphics | Minecraft-esque voxel rendering "engine" with many more features **stb_voxel_render.h** | 0.81 | 3D&nbsp;graphics | 3644 | Minecraft-esque voxel rendering "engine" with many more features
**stb_dxt.h** | 1.04 | 3D&nbsp;graphics | Fabian "ryg" Giesen's real-time DXT compressor **stb_dxt.h** | 1.04 | 3D&nbsp;graphics | 624 | Fabian "ryg" Giesen's real-time DXT compressor
**stb_perlin.h** | 0.2 | 3D&nbsp;graphics | revised Perlin noise (3D input, 1D output) **stb_perlin.h** | 0.2 | 3D&nbsp;graphics | 175 | revised Perlin noise (3D input, 1D output)
**stb_easy_font.h** | 0.5 | 3D&nbsp;graphics | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc **stb_easy_font.h** | 0.5 | 3D&nbsp;graphics | 220 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
**stb_tilemap_editor.h** | 0.30 | game&nbsp;development | embeddable tilemap editor **stb_tilemap_editor.h** | 0.35 | game&nbsp;dev | 4120 | embeddable tilemap editor
**stb_herringbone_wang_tile.h** | 0.6 | game&nbsp;development | herringbone Wang tile map generator **stb_herringbone_wa...** | 0.6 | game&nbsp;dev | 1217 | herringbone Wang tile map generator
**stb_c_lexer.h** | 0.06 | parsing | simplify writing parsers for C-like languages **stb_c_lexer.h** | 0.06 | parsing | 809 | simplify writing parsers for C-like languages
**stb_divide.h** | 0.91 | math | more useful 32-bit modulus e.g. "euclidean divide" **stb_divide.h** | 0.91 | math | 373 | more useful 32-bit modulus e.g. "euclidean divide"
**stb.h** | 2.24 | misc | helper functions for C, mostly redundant in C++; basically author's personal stuff **stb.h** | 2.24 | misc | 14086 | helper functions for C, mostly redundant in C++; basically author's personal stuff
**stb_leakcheck.h** | 0.1 | misc | quick-and-dirty malloc/free leak-checking **stb_leakcheck.h** | 0.2 | misc | 117 | quick-and-dirty malloc/free leak-checking
Total libraries: 18
Total lines of C code: 45274
FAQ FAQ
--- ---
@ -45,6 +51,17 @@ attribution requirement). They may be less featureful, slower,
and/or use more memory. If you're already using an equivalent and/or use more memory. If you're already using an equivalent
library, there's probably no good reason to switch. library, there's probably no good reason to switch.
#### Why do you list "lines of code"? It's a terrible metric.
Just to give you some idea of the internal complexity of the library,
to help you manage your expectations, or to let you know what you're
getting into. While not all the libraries are written in the same
style, they're certainly similar styles, and so comparisons between
the libraries are probably still meaningful.
Note though that the lines do include both the implementation, the
part that corresponds to a header file, and the documentation.
#### Why single-file headers? #### Why single-file headers?
Windows doesn't have standard directories where libraries Windows doesn't have standard directories where libraries
@ -52,12 +69,21 @@ live. That makes deploying libraries in Windows a lot more
painful than open source developers on Unix-derivates generally painful than open source developers on Unix-derivates generally
realize. (It also makes library dependencies a lot worse in Windows.) realize. (It also makes library dependencies a lot worse in Windows.)
There's also a common problem in Windows where a library was built
against a different version of the runtime library, which causes
link conflicts and confusion. Shipping the libs as headers means
you normally just compile them straight into your project without
making libraries, thus sidestepping that problem.
Making them a single file makes it very easy to just Making them a single file makes it very easy to just
drop them into a project that needs them. (Of course you can drop them into a project that needs them. (Of course you can
still put them in a proper shared library tree if you want.) still put them in a proper shared library tree if you want.)
Why not two files, one a header and one an implementation?
The difference between 10 files and 9 files is not a big deal, The difference between 10 files and 9 files is not a big deal,
but the difference between 2 files and 1 file is a big deal. but the difference between 2 files and 1 file is a big deal.
You don't need to zip or tar the files up, you don't have to
remember to attach *two* files, etc.
#### Why "stb"? Is this something to do with Set-Top Boxes? #### Why "stb"? Is this something to do with Set-Top Boxes?
@ -83,12 +109,9 @@ Yes. https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
#### Why public domain? #### Why public domain?
Because more people will use it. Because it's not viral, people I prefer it over GPL, LGPL, BSD, zlib, etc. for many reasons.
are not obligated to give back, so you could argue that it hurts Some of them are listed here:
the *development* of it, and then because it doesn't develop as https://github.com/nothings/stb/blob/master/docs/why_public_domain.md
well it's not as good, and then because it's not as good, in the
long run maybe fewer people will use it. I have total respect for
that opinion, but I just don't believe it myself for most software.
#### Why C? #### Why C?

116
docs/why_public_domain.md Normal file
View File

@ -0,0 +1,116 @@
My collected rationales for placing these libraries
in the public domain:
1. Public domain vs. viral licenses
Why is this library public domain?
Because more people will use it. Because it's not viral, people are
not obligated to give back, so you could argue that it hurts the
development of it, and then because it doesn't develop as well it's
not as good, and then because it's not as good, in the long run
maybe fewer people will use it. I have total respect for that
opinion, but I just don't believe it myself for most software.
2. Public domain vs. attribution-required licenses
The primary difference between public domain and, say, a Creative Commons
commercial / non-share-alike / attribution license is solely the
requirement for attribution. (Similarly the BSD license and such.)
While I would *appreciate* acknowledgement and attribution, I believe
that it is foolish to place a legal encumberment (i.e. a license) on
the software *solely* to get attribution.
In other words, I'm arguing that PD is superior to the BSD license and
the Creative Commons 'Attribution' license. If the license offers
anything besides attribution -- as does, e.g., CC NonCommercial-ShareAlike,
or the GPL -- that's a separate discussion.
3. Other aspects of BSD-style licenses besides attribution
Permissive licenses like zlib and BSD license are perfectly reasonable
in their requirements, but they are very wordy and
have only two benefits over public domain: legally-mandated
attribution and liability-control. I do not believe these
are worth the excessive verbosity and user-unfriendliness
these licenses induce, especially in the single-file
case where those licenses tend to be at the top of
the file, the first thing you see.
To the specific points, I have had no trouble receiving
attribution for my libraries; liability in the face of
no explicit disclaimer of liability is an open question,
but one I have a lot of difficulty imagining there being
any actual doubt about in court. Sometimes I explicitly
note in my libraries that I make no guarantees about them
being fit for purpose, but it's pretty absurd to do this;
as a whole, it comes across as "here is a library to decode
vorbis audio files, but it may not actually work and if
you have problems it's not my fault, but also please
report bugs so I can fix them"--so dumb!
4. full discussion from stb_howto.txt on what YOU should do for YOUR libs
```
EASY-TO-COMPLY LICENSE
I make my libraries public domain. You don't have to.
But my goal in releasing stb-style libraries is to
reduce friction for potential users as much as
possible. That means:
a. easy to build (what this file is mostly about)
b. easy to invoke (which requires good API design)
c. easy to deploy (which is about licensing)
I choose to place all my libraries in the public
domain, abjuring copyright, rather than license
the libraries. This has some benefits and some
drawbacks.
Any license which is "viral" to modifications
causes worries for lawyers, even if their programmers
aren't modifying it.
Any license which requires crediting in documentation
adds friction which can add up. Valve used to have
a page with a list of all of these on their web site,
and it was insane, and obviously nobody ever looked
at it so why would you care whether your credit appeared
there?
Permissive licenses like zlib and BSD license are
perfectly reasonable, but they are very wordy and
have only two benefits over public domain: legally-mandated
attribution and liability-control. I do not believe these
are worth the excessive verbosity and user-unfriendliness
these licenses induce, especially in the single-file
case where those licenses tend to be at the top of
the file, the first thing you see. (To the specific
points, I have had no trouble receiving attribution
for my libraries; liability in the face of no explicit
disclaimer of liability is an open question.)
However, public domain has frictions of its own, because
public domain declarations aren't necessary recognized
in the USA and some other locations. For that reason,
I recommend a declaration along these lines:
// This software is in the public domain. Where that dedication is not
// recognized, you are granted a perpetual, irrevocable license to copy
// and modify this file as you see fit.
I typically place this declaration at the end of the initial
comment block of the file and just say 'public domain'
at the top.
I have had people say they couldn't use one of my
libraries because it was only "public domain" and didn't
have the additional fallback clause, who asked if
I could dual-license it under a traditional license.
My answer: they can create a derivative work by
modifying one character, and then license that however
they like. (Indeed, *adding* the zlib or BSD license
would be such a modification!) Unfortunately, their
lawyers reportedly didn't like that answer. :(
```

2
stb.h
View File

@ -5255,7 +5255,7 @@ int stb_fullpath(char *abs, int abs_size, char *rel)
#ifdef _MSC_VER #ifdef _MSC_VER
return _fullpath(abs, rel, abs_size) != NULL; return _fullpath(abs, rel, abs_size) != NULL;
#else #else
if (abs[0] == '/' || abs[0] == '~') { if (rel[0] == '/' || rel[0] == '~') {
if ((int) strlen(rel) >= abs_size) if ((int) strlen(rel) >= abs_size)
return 0; return 0;
strcpy(abs,rel); strcpy(abs,rel);

View File

@ -1,4 +1,4 @@
/* stb_image - v2.03 - public domain image loader - http://nothings.org/stb_image.h /* stb_image - v2.06 - public domain image loader - http://nothings.org/stb_image.h
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@ -143,6 +143,9 @@
Latest revision history: Latest revision history:
2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
2.03 (2015-04-12) additional corruption checking 2.03 (2015-04-12) additional corruption checking
stbi_set_flip_vertically_on_load stbi_set_flip_vertically_on_load
fix NEON support; fix mingw support fix NEON support; fix mingw support
@ -159,8 +162,6 @@
1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted) 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted)
optimize PNG optimize PNG
fix bug in interlaced PNG with user-specified channel count fix bug in interlaced PNG with user-specified channel count
1.46 (2014-08-26) fix broken tRNS chunk in non-paletted PNG
1.45 (2014-08-16) workaround MSVC-ARM internal compiler error by wrapping malloc
See end of file for full revision history. See end of file for full revision history.
@ -633,11 +634,14 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
#endif #endif
// x86/x64 detection // x86/x64 detection
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) #if defined(__x86_64__) || defined(_M_X64)
#define STBI__X64_TARGET
#elif defined(__i386) || defined(_M_IX86)
#define STBI__X86_TARGET #define STBI__X86_TARGET
#endif #endif
#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) #if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
// NOTE: not clear do we actually need this for the 64-bit path?
// gcc doesn't support sse2 intrinsics unless you compile with -msse2, // gcc doesn't support sse2 intrinsics unless you compile with -msse2,
// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; // (but compiling with -msse2 allows the compiler to use SSE2 everywhere;
// this is just broken and gcc are jerks for not fixing it properly // this is just broken and gcc are jerks for not fixing it properly
@ -646,6 +650,8 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
#endif #endif
#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) #if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
//
// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the // 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. // Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not // As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
@ -1640,7 +1646,7 @@ 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 sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
k = stbi_lrot(j->code_buffer, n); k = stbi_lrot(j->code_buffer, n);
STBI_ASSERT(n >= 0 && n < sizeof(stbi__bmask)/sizeof(*stbi__bmask)); STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
j->code_buffer = k & ~stbi__bmask[n]; j->code_buffer = k & ~stbi__bmask[n];
k &= stbi__bmask[n]; k &= stbi__bmask[n];
j->code_bits -= n; j->code_bits -= n;
@ -1846,8 +1852,11 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
if (r) if (r)
j->eob_run += stbi__jpeg_get_bits(j, r); j->eob_run += stbi__jpeg_get_bits(j, r);
r = 64; // force end of block r = 64; // force end of block
} else } else {
r = 16; // r=15 is the code for 16 0s // r=15 s=0 should write 16 0s, so we just do
// a run of 15 0s and then write s (which is 0),
// so we don't have to do anything special here
}
} else { } else {
if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
// sign bit // sign bit
@ -1859,7 +1868,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
// advance by r // advance by r
while (k <= j->spec_end) { while (k <= j->spec_end) {
short *p = &data[stbi__jpeg_dezigzag[k]]; short *p = &data[stbi__jpeg_dezigzag[k++]];
if (*p != 0) { if (*p != 0) {
if (stbi__jpeg_get_bit(j)) if (stbi__jpeg_get_bit(j))
if ((*p & bit)==0) { if ((*p & bit)==0) {
@ -1868,15 +1877,12 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
else else
*p -= bit; *p -= bit;
} }
++k;
} else { } else {
if (r == 0) { if (r == 0) {
if (s) *p = (short) s;
data[stbi__jpeg_dezigzag[k++]] = (short) s;
break; break;
} }
--r; --r;
++k;
} }
} }
} while (k <= j->spec_end); } while (k <= j->spec_end);
@ -5134,7 +5140,8 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
p = out+channel; p = out+channel;
if (channel >= channelCount) { if (channel >= channelCount) {
// Fill this channel with default data. // Fill this channel with default data.
for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4; for (i = 0; i < pixelCount; i++, p += 4)
*p = (channel == 3 ? 255 : 0);
} else { } else {
// Read the RLE data. // Read the RLE data.
count = 0; count = 0;
@ -5180,11 +5187,12 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
p = out + channel; p = out + channel;
if (channel > channelCount) { if (channel > channelCount) {
// Fill this channel with default data. // Fill this channel with default data.
for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4; for (i = 0; i < pixelCount; i++, p += 4)
*p = channel == 3 ? 255 : 0;
} else { } else {
// Read the data. // Read the data.
for (i = 0; i < pixelCount; i++) for (i = 0; i < pixelCount; i++, p += 4)
*p = stbi__get8(s), p += 4; *p = stbi__get8(s);
} }
} }
} }
@ -5194,7 +5202,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
if (out == NULL) return out; // stbi__convert_format frees input on failure if (out == NULL) return out; // stbi__convert_format frees input on failure
} }
if (comp) *comp = channelCount; if (comp) *comp = 4;
*y = h; *y = h;
*x = w; *x = w;
@ -6287,6 +6295,9 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
/* /*
revision history: revision history:
2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
2.03 (2015-04-12) extra corruption checking (mmozeiko) 2.03 (2015-04-12) extra corruption checking (mmozeiko)
stbi_set_flip_vertically_on_load (nguillemot) stbi_set_flip_vertically_on_load (nguillemot)
fix NEON support; fix mingw support fix NEON support; fix mingw support

View File

@ -1,4 +1,4 @@
// stb_leakcheck.h - v0.1 - quick & dirty malloc leak-checking - public domain // stb_leakcheck.h - v0.2 - quick & dirty malloc leak-checking - public domain
#ifdef STB_LEAKCHECK_IMPLEMENTATION #ifdef STB_LEAKCHECK_IMPLEMENTATION
#undef STB_LEAKCHECK_IMPLEMENTATION // don't implenment more than once #undef STB_LEAKCHECK_IMPLEMENTATION // don't implenment more than once
@ -27,7 +27,7 @@ static stb_leakcheck_malloc_info *mi_head;
void *stb_leakcheck_malloc(size_t sz, char *file, int line) void *stb_leakcheck_malloc(size_t sz, char *file, int line)
{ {
stb_leakcheck_malloc_info *mi = malloc(sz + sizeof(*mi)); stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi));
if (mi == NULL) return mi; if (mi == NULL) return mi;
mi->file = file; mi->file = file;
mi->line = line; mi->line = line;

View File

@ -1,4 +1,4 @@
// stb_rect_pack.h - v0.05 - public domain - rectangle packing // stb_rect_pack.h - v0.06 - public domain - rectangle packing
// Sean Barrett 2014 // Sean Barrett 2014
// //
// Useful for e.g. packing rectangular textures into an atlas. // Useful for e.g. packing rectangular textures into an atlas.
@ -13,6 +13,7 @@
// More docs to come. // More docs to come.
// //
// No memory allocations; uses qsort() and assert() from stdlib. // No memory allocations; uses qsort() and assert() from stdlib.
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
// //
// This library currently uses the Skyline Bottom-Left algorithm. // This library currently uses the Skyline Bottom-Left algorithm.
// //
@ -20,8 +21,18 @@
// implement them to the same API, but with a different init // implement them to the same API, but with a different init
// function. // function.
// //
// Credits
//
// Library
// Sean Barrett
// Minor features
// Martins Mozeiko
// Bugfixes / warning fixes
// [your name could be here]
//
// Version history: // Version history:
// //
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert // 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support // 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release // 0.01: initial release
@ -169,7 +180,10 @@ struct stbrp_context
// //
#ifdef STB_RECT_PACK_IMPLEMENTATION #ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h> #include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT #ifndef STBRP_ASSERT
#include <assert.h> #include <assert.h>
@ -524,7 +538,7 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n
} }
// sort according to heuristic // sort according to heuristic
qsort(rects, num_rects, sizeof(rects[0]), rect_height_compare); STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) { for (i=0; i < num_rects; ++i) {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
@ -537,7 +551,7 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n
} }
// unsort // unsort
qsort(rects, num_rects, sizeof(rects[0]), rect_original_order); STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
// set was_packed flags // set was_packed flags
for (i=0; i < num_rects; ++i) for (i=0; i < num_rects; ++i)

View File

@ -1,4 +1,4 @@
// stb_textedit.h - v1.5 - public domain - Sean Barrett // stb_textedit.h - v1.6 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools // Development of this library was sponsored by RAD Game Tools
// //
// This C header file implements the guts of a multi-line text-editing // This C header file implements the guts of a multi-line text-editing
@ -24,12 +24,14 @@
// //
// DEPENDENCIES // DEPENDENCIES
// //
// Uses the C runtime function 'memmove'. Uses no other functions. // Uses the C runtime function 'memmove', which you can override
// Performs no runtime allocations. // by defining STB_TEXTEDIT_memmove before the implementation.
// Uses no other functions. Performs no runtime allocations.
// //
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove
// 1.5 (2014-09-10) add support for secondary keys for OS X // 1.5 (2014-09-10) add support for secondary keys for OS X
// 1.4 (2014-08-17) fix signed/unsigned warnings // 1.4 (2014-08-17) fix signed/unsigned warnings
// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary // 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
@ -45,6 +47,7 @@
// Ulf Winklemann: move-by-word in 1.1 // Ulf Winklemann: move-by-word in 1.1
// Scott Graham: mouse selection bugfix in 1.3 // Scott Graham: mouse selection bugfix in 1.3
// Fabian Giesen: secondary key inputs in 1.5 // Fabian Giesen: secondary key inputs in 1.5
// Martins Mozeiko: STB_TEXTEDIT_memmove
// //
// USAGE // USAGE
// //
@ -358,7 +361,10 @@ typedef struct
// included just the "header" portion // included just the "header" portion
#ifdef STB_TEXTEDIT_IMPLEMENTATION #ifdef STB_TEXTEDIT_IMPLEMENTATION
#include <string.h> // memmove #ifndef STB_TEXTEDIT_memmove
#include <string.h>
#define STB_TEXTEDIT_memmove memmove
#endif
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@ -1038,13 +1044,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
int n = state->undo_rec[0].insert_length, i; int n = state->undo_rec[0].insert_length, i;
// delete n characters from all other records // delete n characters from all other records
state->undo_char_point = state->undo_char_point - (short) n; // vsnet05 state->undo_char_point = state->undo_char_point - (short) n; // vsnet05
memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
for (i=0; i < state->undo_point; ++i) for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0) if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it
} }
--state->undo_point; --state->undo_point;
memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
} }
} }
@ -1062,13 +1068,13 @@ static void stb_textedit_discard_redo(StbUndoState *state)
int n = state->undo_rec[k].insert_length, i; int n = state->undo_rec[k].insert_length, i;
// delete n characters from all other records // delete n characters from all other records
state->redo_char_point = state->redo_char_point + (short) n; // vsnet05 state->redo_char_point = state->redo_char_point + (short) n; // vsnet05
memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
for (i=state->redo_point; i < k; ++i) for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0) if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05 state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
} }
++state->redo_point; ++state->redo_point;
memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0]))); STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
} }
} }

View File

@ -1,4 +1,4 @@
// stb_tilemap_editor.h - v0.30 - Sean Barrett - http://nothings.org/stb // stb_tilemap_editor.h - v0.35 - Sean Barrett - http://nothings.org/stb
// placed in the public domain - not copyrighted - first released 2014-09 // placed in the public domain - not copyrighted - first released 2014-09
// //
// Embeddable tilemap editor for C/C++ // Embeddable tilemap editor for C/C++
@ -275,6 +275,10 @@
// either approach allows cut&pasting between levels.) // either approach allows cut&pasting between levels.)
// //
// REVISION HISTORY // REVISION HISTORY
// 0.35 layername button changes
// - layername buttons grow with the layer panel
// - fix stbte_create_map being declared as stbte_create
// - fix declaration of stbte_create_map
// 0.30 properties release // 0.30 properties release
// - properties panel for editing user-defined "object" properties // - properties panel for editing user-defined "object" properties
// - can link each tile to one other tile // - can link each tile to one other tile
@ -296,11 +300,16 @@
// Support STBTE_HITTEST_TILE above // Support STBTE_HITTEST_TILE above
// ?Cancel drags by clicking other button? - may be fixed // ?Cancel drags by clicking other button? - may be fixed
// Finish support for toolbar at side // Finish support for toolbar at side
// Layer name buttons grow to fill box
// //
// CREDITS // CREDITS
// //
// Written by Sean Barrett, September & October 2014. //
// Main editor & features
// Sean Barrett
// Additional features:
// Josh Huelsman
// Bugfixes:
// [this could be you!]
// //
// LICENSE // LICENSE
// //
@ -339,7 +348,7 @@ enum
// creation // creation
// //
extern stbte_tilemap *stbte_create(int map_x, int map_y, int map_layers, int spacing_x, int spacing_y, int max_tiles); extern stbte_tilemap *stbte_create_map(int map_x, int map_y, int map_layers, int spacing_x, int spacing_y, int max_tiles);
// create an editable tilemap // create an editable tilemap
// map_x : dimensions of map horizontally (user can change this in editor), <= STBTE_MAX_TILEMAP_X // map_x : dimensions of map horizontally (user can change this in editor), <= STBTE_MAX_TILEMAP_X
// map_y : dimensions of map vertically (user can change this in editor) <= STBTE_MAX_TILEMAP_Y // map_y : dimensions of map vertically (user can change this in editor) <= STBTE_MAX_TILEMAP_Y
@ -352,7 +361,7 @@ extern stbte_tilemap *stbte_create(int map_x, int map_y, int map_layers, int spa
extern void stbte_define_tile(stbte_tilemap *tm, unsigned short id, unsigned int layermask, const char * category); extern void stbte_define_tile(stbte_tilemap *tm, unsigned short id, unsigned int layermask, const char * category);
// call this repeatedly for each tile to install the tile definitions into the editable tilemap // call this repeatedly for each tile to install the tile definitions into the editable tilemap
// tm : tilemap created by stbte_create // tm : tilemap created by stbte_create_map
// id : unique identifier for each tile, 0 <= id < 32768 // id : unique identifier for each tile, 0 <= id < 32768
// layermask : bitmask of which layers tile is allowed on: 1 = layer 0, 255 = layers 0..7 // layermask : bitmask of which layers tile is allowed on: 1 = layer 0, 255 = layers 0..7
// (note that onscreen, the editor numbers the layers from 1 not 0) // (note that onscreen, the editor numbers the layers from 1 not 0)
@ -938,6 +947,7 @@ struct stbte_tilemap
int tileinfo_dirty; int tileinfo_dirty;
stbte__layer layerinfo[STBTE_MAX_LAYERS]; stbte__layer layerinfo[STBTE_MAX_LAYERS];
int has_layer_names; int has_layer_names;
int layername_width;
int layer_scroll; int layer_scroll;
int propmode; int propmode;
int solo_layer; int solo_layer;
@ -1016,6 +1026,7 @@ stbte_tilemap *stbte_create_map(int map_x, int map_y, int map_layers, int spacin
tm->layer_scroll = 0; tm->layer_scroll = 0;
tm->propmode = 0; tm->propmode = 0;
tm->has_layer_names = 0; tm->has_layer_names = 0;
tm->layername_width = 0;
tm->undo_available_valid = 0; tm->undo_available_valid = 0;
for (i=0; i < tm->num_layers; ++i) { for (i=0; i < tm->num_layers; ++i) {
@ -1088,12 +1099,17 @@ void stbte_define_tile(stbte_tilemap *tm, unsigned short id, unsigned int layerm
tm->tileinfo_dirty = 1; tm->tileinfo_dirty = 1;
} }
static int stbte__text_width(const char *str);
void stbte_set_layername(stbte_tilemap *tm, int layer, const char *layername) void stbte_set_layername(stbte_tilemap *tm, int layer, const char *layername)
{ {
STBTE_ASSERT(layer >= 0 && layer < tm->num_layers); STBTE_ASSERT(layer >= 0 && layer < tm->num_layers);
if (layer >= 0 && layer < tm->num_layers) { if (layer >= 0 && layer < tm->num_layers) {
int width;
tm->layerinfo[layer].name = layername; tm->layerinfo[layer].name = layername;
tm->has_layer_names = 1; tm->has_layer_names = 1;
width = stbte__text_width(layername);
tm->layername_width = (width > tm->layername_width ? width : tm->layername_width);
} }
} }
@ -3382,14 +3398,21 @@ static void stbte__info(stbte_tilemap *tm, int x0, int y0, int w, int h)
static void stbte__layers(stbte_tilemap *tm, int x0, int y0, int w, int h) static void stbte__layers(stbte_tilemap *tm, int x0, int y0, int w, int h)
{ {
int i, y, n;
int x1 = x0+w;
int y1 = y0+h;
int xoff = tm->has_layer_names ? 50 : 20;
static char *propmodes[3] = { static char *propmodes[3] = {
"default", "always", "never" "default", "always", "never"
}; };
int num_rows; int num_rows;
int i, y, n;
int x1 = x0+w;
int y1 = y0+h;
int xoff = 20;
if (tm->has_layer_names) {
int side = stbte__ui.panel[STBTE__panel_layers].side;
xoff = stbte__region[side].width - 42;
xoff = (xoff < tm->layername_width + 10 ? xoff : tm->layername_width + 10);
}
x0 += 2; x0 += 2;
y0 += 5; y0 += 5;
if (!tm->has_layer_names) { if (!tm->has_layer_names) {
@ -3427,7 +3450,7 @@ static void stbte__layers(stbte_tilemap *tm, int x0, int y0, int w, int h)
n = stbte__text_width("prop:")+2; n = stbte__text_width("prop:")+2;
stbte__draw_text(x0,y+2, "prop:", w, STBTE__TEXTCOLOR(STBTE__cpanel)); stbte__draw_text(x0,y+2, "prop:", w, STBTE__TEXTCOLOR(STBTE__cpanel));
i = w - n - 4; i = w - n - 4;
if (i > 45) i = 45; if (i > 50) i = 50;
if (stbte__button(STBTE__clayer_button, propmodes[tm->propmode], x0+n,y,0,i, STBTE__ID(STBTE__layer,256), 0,0)) if (stbte__button(STBTE__clayer_button, propmodes[tm->propmode], x0+n,y,0,i, STBTE__ID(STBTE__layer,256), 0,0))
tm->propmode = (tm->propmode+1)%3; tm->propmode = (tm->propmode+1)%3;
#endif #endif

View File

@ -1,4 +1,4 @@
// stb_truetype.h - v1.03 - public domain // stb_truetype.h - v1.06 - public domain
// authored from 2009-2014 by Sean Barrett / RAD Game Tools // authored from 2009-2014 by Sean Barrett / RAD Game Tools
// //
// This library processes TrueType files: // This library processes TrueType files:
@ -38,12 +38,18 @@
// Cap Petschulat // Cap Petschulat
// Omar Cornut // Omar Cornut
// github:aloucks // github:aloucks
// Peter LaValle
// //
// Misc other: // Misc other:
// Ryan Gordon // Ryan Gordon
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
// also more precise AA rasterizer, except if shapes overlap
// remove need for STBTT_sort
// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
// 1.04 (2015-04-15) typo in example
// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
@ -117,6 +123,15 @@
// stbtt_GetFontVMetrics() // stbtt_GetFontVMetrics()
// stbtt_GetCodepointKernAdvance() // stbtt_GetCodepointKernAdvance()
// //
// Starting with version 1.06, the rasterizer was replaced with a new,
// faster and generally-more-precise rasterizer. The new rasterizer more
// accurately measures pixel coverage for anti-aliasing, except in the case
// where multiple shapes overlap, in which case it overestimates the AA pixel
// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
// this turns out to be a problem, you can re-enable the old rasterizer with
// #define STBTT_RASTERIZER_VERSION 1
// which will incur about a 15% speed hit.
//
// ADDITIONAL DOCUMENTATION // ADDITIONAL DOCUMENTATION
// //
// Immediately after this block comment are a series of sample programs. // Immediately after this block comment are a series of sample programs.
@ -216,7 +231,15 @@
// Baked bitmap interface 70 LOC / // Baked bitmap interface 70 LOC /
// Font name matching & access 150 LOC ---- 150 // Font name matching & access 150 LOC ---- 150
// C runtime library abstraction 60 LOC ---- 60 // C runtime library abstraction 60 LOC ---- 60
//
//
// PERFORMANCE MEASUREMENTS FOR 1.06:
//
// 32-bit 64-bit
// Previous release: 8.83 s 7.68 s
// Pool allocations: 7.72 s 6.34 s
// Inline sort : 6.54 s 5.65 s
// New rasterizer : 5.63 s 5.00 s
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -239,7 +262,7 @@ GLuint ftex;
void my_stbtt_initfont(void) void my_stbtt_initfont(void)
{ {
fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
stbtt_BakeFontBitmap(data,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits! stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
// can free ttf_buffer at this point // can free ttf_buffer at this point
glGenTextures(1, &ftex); glGenTextures(1, &ftex);
glBindTexture(GL_TEXTURE_2D, ftex); glBindTexture(GL_TEXTURE_2D, ftex);
@ -327,7 +350,7 @@ int main(int arg, char **argv)
stbtt_fontinfo font; stbtt_fontinfo font;
int i,j,ascent,baseline,ch=0; int i,j,ascent,baseline,ch=0;
float scale, xpos=2; // leave a little padding in case the character extends left float scale, xpos=2; // leave a little padding in case the character extends left
char *text = "Heljo World!"; char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
stbtt_InitFont(&font, buffer, 0); stbtt_InitFont(&font, buffer, 0);
@ -385,18 +408,6 @@ int main(int arg, char **argv)
typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
#ifdef STBTT_STATIC
#define STBTT_DEF static
#else
#define STBTT_DEF extern
#endif
// #define your own STBTT_sort() to override this to avoid qsort
#ifndef STBTT_sort
#include <stdlib.h>
#define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
#endif
// #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
#ifndef STBTT_ifloor #ifndef STBTT_ifloor
#include <math.h> #include <math.h>
@ -443,6 +454,12 @@ int main(int arg, char **argv)
#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
#define __STB_INCLUDE_STB_TRUETYPE_H__ #define __STB_INCLUDE_STB_TRUETYPE_H__
#ifdef STBTT_STATIC
#define STBTT_DEF static
#else
#define STBTT_DEF extern
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -899,6 +916,10 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
#ifndef STBTT_RASTERIZER_VERSION
#define STBTT_RASTERIZER_VERSION 2
#endif
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// //
// accessors to parse data from file // accessors to parse data from file
@ -1547,42 +1568,129 @@ STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codep
stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
} }
//////////////////////////////////////////////////////////////////////////////
//
// Rasterizer
typedef struct stbtt__hheap_chunk
{
struct stbtt__hheap_chunk *next;
} stbtt__hheap_chunk;
typedef struct stbtt__hheap
{
struct stbtt__hheap_chunk *head;
void *first_free;
int num_remaining_in_head_chunk;
} stbtt__hheap;
static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
{
if (hh->first_free) {
void *p = hh->first_free;
hh->first_free = * (void **) p;
return p;
} else {
if (hh->num_remaining_in_head_chunk == 0) {
int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
if (c == NULL)
return NULL;
c->next = hh->head;
hh->head = c;
hh->num_remaining_in_head_chunk = count;
}
--hh->num_remaining_in_head_chunk;
return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk;
}
}
static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
{
*(void **) p = hh->first_free;
hh->first_free = p;
}
static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
{
stbtt__hheap_chunk *c = hh->head;
while (c) {
stbtt__hheap_chunk *n = c->next;
STBTT_free(c, userdata);
c = n;
}
}
typedef struct stbtt__edge { typedef struct stbtt__edge {
float x0,y0, x1,y1; float x0,y0, x1,y1;
int invert; int invert;
} stbtt__edge; } stbtt__edge;
typedef struct stbtt__active_edge typedef struct stbtt__active_edge
{ {
struct stbtt__active_edge *next;
#if STBTT_RASTERIZER_VERSION==1
int x,dx; int x,dx;
float ey; float ey;
struct stbtt__active_edge *next; int direction;
int valid; #elif STBTT_RASTERIZER_VERSION==2
float fx,fdx,fdy;
float direction;
float sy;
float ey;
#else
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
#endif
} stbtt__active_edge; } stbtt__active_edge;
#define FIXSHIFT 10 #if STBTT_RASTERIZER_VERSION == 1
#define FIX (1 << FIXSHIFT) #define STBTT_FIXSHIFT 10
#define FIXMASK (FIX-1) #define STBTT_FIX (1 << STBTT_FIXSHIFT)
#define STBTT_FIXMASK (STBTT_FIX-1)
static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata) static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
{ {
stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!! stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
STBTT_assert(e->y0 <= start_point);
if (!z) return z; if (!z) return z;
// round dx down to avoid going too far
// round dx down to avoid overshooting
if (dxdy < 0) if (dxdy < 0)
z->dx = -STBTT_ifloor(FIX * -dxdy); z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
else else
z->dx = STBTT_ifloor(FIX * dxdy); z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
z->x -= off_x * FIX; z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
z->x -= off_x * STBTT_FIX;
z->ey = e->y1; z->ey = e->y1;
z->next = 0; z->next = 0;
z->valid = e->invert ? 1 : -1; z->direction = e->invert ? 1 : -1;
return z; return z;
} }
#elif STBTT_RASTERIZER_VERSION == 2
static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
{
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
//STBTT_assert(e->y0 <= start_point);
if (!z) return z;
z->fdx = dxdy;
z->fdy = (1/dxdy);
z->fx = e->x0 + dxdy * (start_point - e->y0);
z->fx -= off_x;
z->direction = e->invert ? 1.0f : -1.0f;
z->sy = e->y0;
z->ey = e->y1;
z->next = 0;
return z;
}
#else
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
#endif
#if STBTT_RASTERIZER_VERSION == 1
// note: this routine clips fills that extend off the edges... ideally this // note: this routine clips fills that extend off the edges... ideally this
// wouldn't happen, but it could happen if the truetype glyph bounding boxes // wouldn't happen, but it could happen if the truetype glyph bounding boxes
// are wrong, or if the user supplies a too-small bitmap // are wrong, or if the user supplies a too-small bitmap
@ -1594,26 +1702,26 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
while (e) { while (e) {
if (w == 0) { if (w == 0) {
// if we're currently at zero, we need to record the edge start point // if we're currently at zero, we need to record the edge start point
x0 = e->x; w += e->valid; x0 = e->x; w += e->direction;
} else { } else {
int x1 = e->x; w += e->valid; int x1 = e->x; w += e->direction;
// if we went to zero, we need to draw // if we went to zero, we need to draw
if (w == 0) { if (w == 0) {
int i = x0 >> FIXSHIFT; int i = x0 >> STBTT_FIXSHIFT;
int j = x1 >> FIXSHIFT; int j = x1 >> STBTT_FIXSHIFT;
if (i < len && j >= 0) { if (i < len && j >= 0) {
if (i == j) { if (i == j) {
// x0,x1 are the same pixel, so compute combined coverage // x0,x1 are the same pixel, so compute combined coverage
scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT); scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
} else { } else {
if (i >= 0) // add antialiasing for x0 if (i >= 0) // add antialiasing for x0
scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT); scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
else else
i = -1; // clip i = -1; // clip
if (j < len) // add antialiasing for x1 if (j < len) // add antialiasing for x1
scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT); scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
else else
j = len; // clip j = len; // clip
@ -1630,6 +1738,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
{ {
stbtt__hheap hh = { 0 };
stbtt__active_edge *active = NULL; stbtt__active_edge *active = NULL;
int y,j=0; int y,j=0;
int max_weight = (255 / vsubsample); // weight per vertical scanline int max_weight = (255 / vsubsample); // weight per vertical scanline
@ -1657,9 +1766,9 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
stbtt__active_edge * z = *step; stbtt__active_edge * z = *step;
if (z->ey <= scan_y) { if (z->ey <= scan_y) {
*step = z->next; // delete from list *step = z->next; // delete from list
STBTT_assert(z->valid); STBTT_assert(z->direction);
z->valid = 0; z->direction = 0;
STBTT_free(z, userdata); stbtt__hheap_free(&hh, z);
} else { } else {
z->x += z->dx; // advance to position for current scanline z->x += z->dx; // advance to position for current scanline
step = &((*step)->next); // advance through list step = &((*step)->next); // advance through list
@ -1688,7 +1797,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
// insert all edges that start before the center of this scanline -- omit ones that also end on this scanline // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
while (e->y0 <= scan_y) { while (e->y0 <= scan_y) {
if (e->y1 > scan_y) { if (e->y1 > scan_y) {
stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata); stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
// find insertion point // find insertion point
if (active == NULL) if (active == NULL)
active = z; active = z;
@ -1719,24 +1828,377 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
++j; ++j;
} }
while (active) { stbtt__hheap_cleanup(&hh, userdata);
stbtt__active_edge *z = active;
active = active->next;
STBTT_free(z, userdata);
}
if (scanline != scanline_data) if (scanline != scanline_data)
STBTT_free(scanline, userdata); STBTT_free(scanline, userdata);
} }
static int stbtt__edge_compare(const void *p, const void *q) #elif STBTT_RASTERIZER_VERSION == 2
{
stbtt__edge *a = (stbtt__edge *) p;
stbtt__edge *b = (stbtt__edge *) q;
if (a->y0 < b->y0) return -1; // the edge passed in here does not cross the vertical line at x or the vertical line at x+1
if (a->y0 > b->y0) return 1; // (i.e. it has already been clipped to those)
return 0; static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
{
if (y0 == y1) return;
assert(y0 < y1);
assert(e->sy <= e->ey);
if (y0 > e->ey) return;
if (y1 < e->sy) return;
if (y0 < e->sy) {
x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
y0 = e->sy;
}
if (y1 > e->ey) {
x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
y1 = e->ey;
}
if (x0 == x)
assert(x1 <= x+1);
else if (x0 == x+1)
assert(x1 >= x);
else if (x0 <= x)
assert(x1 <= x);
else if (x0 >= x+1)
assert(x1 >= x+1);
else
assert(x1 >= x && x1 <= x+1);
if (x0 <= x && x1 <= x)
scanline[x] += e->direction * (y1-y0);
else if (x0 >= x+1 && x1 >= x+1)
;
else {
assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
}
}
static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
{
float y_bottom = y_top+1;
while (e) {
// brute force every pixel
// compute intersection points with top & bottom
assert(e->ey >= y_top);
if (e->fdx == 0) {
float x0 = e->fx;
if (x0 < len) {
if (x0 >= 0) {
stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
} else {
stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
}
}
} else {
float x0 = e->fx;
float dx = e->fdx;
float xb = x0 + dx;
float x_top, x_bottom;
float y0,y1;
float dy = e->fdy;
assert(e->sy <= y_bottom && e->ey >= y_top);
// compute endpoints of line segment clipped to this scanline (if the
// line segment starts on this scanline. x0 is the intersection of the
// line with y_top, but that may be off the line segment.
if (e->sy > y_top) {
x_top = x0 + dx * (e->sy - y_top);
y0 = e->sy;
} else {
x_top = x0;
y0 = y_top;
}
if (e->ey < y_bottom) {
x_bottom = x0 + dx * (e->ey - y_top);
y1 = e->ey;
} else {
x_bottom = xb;
y1 = y_bottom;
}
if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
// from here on, we don't have to range check x values
if ((int) x_top == (int) x_bottom) {
float height;
// simple case, only spans one pixel
int x = (int) x_top;
height = y1 - y0;
assert(x >= 0 && x < len);
scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
} else {
int x,x1,x2;
float y_crossing, step, sign, area;
// covers 2+ pixels
if (x_top > x_bottom) {
// flip scanline vertically; signed area is the same
float t;
y0 = y_bottom - (y0 - y_top);
y1 = y_bottom - (y1 - y_top);
t = y0, y0 = y1, y1 = t;
t = x_bottom, x_bottom = x_top, x_top = t;
dx = -dx;
dy = -dy;
t = x0, x0 = xb, xb = t;
}
x1 = (int) x_top;
x2 = (int) x_bottom;
// compute intersection with y axis at x1+1
y_crossing = (x1+1 - x0) * dy + y_top;
sign = e->direction;
// area of the rectangle covered from y0..y_crossing
area = sign * (y_crossing-y0);
// area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
step = sign * dy;
for (x = x1+1; x < x2; ++x) {
scanline[x] += area + step/2;
area += step;
}
y_crossing += dy * (x2 - (x1+1));
assert(fabs(area) <= 1.01f);
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (y1-y_crossing);
scanline_fill[x2] += sign * (y1-y0);
}
} else {
// if edge goes outside of box we're drawing, we require
// clipping logic. since this does not match the intended use
// of this library, we use a different, very slow brute
// force implementation
int x;
for (x=0; x < len; ++x) {
// cases:
//
// there can be up to two intersections with the pixel. any intersection
// with left or right edges can be handled by splitting into two (or three)
// regions. intersections with top & bottom do not necessitate case-wise logic.
float y0,y1;
float y_cur = y_top, x_cur = x0;
// x = e->x + e->dx * (y-y_top)
// (y-y_top) = (x - e->x) / e->dx
// y = (x - e->x) / e->dx + y_top
y0 = (x - x0) / dx + y_top;
y1 = (x+1 - x0) / dx + y_top;
if (y0 < y1) {
if (y0 > y_top && y0 < y_bottom) {
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x,y0);
y_cur = y0;
x_cur = (float) x;
}
if (y1 >= y_cur && y1 < y_bottom) {
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x+1,y1);
y_cur = y1;
x_cur = (float) x+1;
}
} else {
if (y1 >= y_cur && y1 < y_bottom) {
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x+1,y1);
y_cur = y1;
x_cur = (float) x+1;
}
if (y0 > y_top && y0 < y_bottom) {
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, (float) x,y0);
y_cur = y0;
x_cur = (float) x;
}
}
stbtt__handle_clipped_edge(scanline,x,e, x_cur,y_cur, xb,y_bottom);
}
}
}
e = e->next;
}
}
// directly AA rasterize edges w/o supersampling
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
{
stbtt__hheap hh = { 0 };
stbtt__active_edge *active = NULL;
int y,j=0, i;
float scanline_data[129], *scanline, *scanline2;
if (result->w > 64)
scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
else
scanline = scanline_data;
scanline2 = scanline + result->w;
y = off_y;
e[n].y0 = (float) (off_y + result->h) + 1;
while (j < result->h) {
// find center of pixel for this scanline
float scan_y_top = y + 0.0f;
float scan_y_bottom = y + 1.0f;
stbtt__active_edge **step = &active;
STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
// update all active edges;
// remove all active edges that terminate before the top of this scanline
while (*step) {
stbtt__active_edge * z = *step;
if (z->ey <= scan_y_top) {
*step = z->next; // delete from list
STBTT_assert(z->direction);
z->direction = 0;
stbtt__hheap_free(&hh, z);
} else {
step = &((*step)->next); // advance through list
}
}
// insert all edges that start before the bottom of this scanline
while (e->y0 <= scan_y_bottom) {
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
assert(z->ey >= scan_y_top);
// insert at front
z->next = active;
active = z;
++e;
}
// now process all active edges
if (active)
stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
{
float sum = 0;
for (i=0; i < result->w; ++i) {
float k;
int m;
sum += scanline2[i];
k = scanline[i] + sum;
k = (float) fabs(k)*255 + 0.5f;
m = (int) k;
if (m > 255) m = 255;
result->pixels[j*result->stride + i] = (unsigned char) m;
}
}
// advance all the edges
step = &active;
while (*step) {
stbtt__active_edge *z = *step;
z->fx += z->fdx; // advance to position for current scanline
step = &((*step)->next); // advance through list
}
++y;
++j;
}
stbtt__hheap_cleanup(&hh, userdata);
if (scanline != scanline_data)
STBTT_free(scanline, userdata);
}
#else
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
#endif
#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
{
int i,j;
for (i=1; i < n; ++i) {
stbtt__edge t = p[i], *a = &t;
j = i;
while (j > 0) {
stbtt__edge *b = &p[j-1];
int c = STBTT__COMPARE(a,b);
if (!c) break;
p[j] = p[j-1];
--j;
}
if (i != j)
p[j] = t;
}
}
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
{
/* threshhold for transitioning to insertion sort */
while (n > 12) {
stbtt__edge t;
int c01,c12,c,m,i,j;
/* compute median of three */
m = n >> 1;
c01 = STBTT__COMPARE(&p[0],&p[m]);
c12 = STBTT__COMPARE(&p[m],&p[n-1]);
/* if 0 >= mid >= end, or 0 < mid < end, then use mid */
if (c01 != c12) {
/* otherwise, we'll need to swap something else to middle */
int z;
c = STBTT__COMPARE(&p[0],&p[n-1]);
/* 0>mid && mid<n: 0>n => n; 0<n => 0 */
/* 0<mid && mid>n: 0>n => 0; 0<n => n */
z = (c == c12) ? 0 : n-1;
t = p[z];
p[z] = p[m];
p[m] = t;
}
/* now p[m] is the median-of-three */
/* swap it to the beginning so it won't move around */
t = p[0];
p[0] = p[m];
p[m] = t;
/* partition loop */
i=1;
j=n-1;
for(;;) {
/* handling of equality is crucial here */
/* for sentinels & efficiency with duplicates */
for (;;++i) {
if (!STBTT__COMPARE(&p[i], &p[0])) break;
}
for (;;--j) {
if (!STBTT__COMPARE(&p[0], &p[j])) break;
}
/* make sure we haven't crossed */
if (i >= j) break;
t = p[i];
p[i] = p[j];
p[j] = t;
++i;
--j;
}
/* recurse on smaller side, iterate on larger */
if (j < (n-i)) {
stbtt__sort_edges_quicksort(p,j);
p = p+i;
n = n-i;
} else {
stbtt__sort_edges_quicksort(p+i, n-i);
n = j;
}
}
}
static void stbtt__sort_edges(stbtt__edge *p, int n)
{
stbtt__sort_edges_quicksort(p, n);
stbtt__sort_edges_ins_sort(p, n);
} }
typedef struct typedef struct
@ -1749,7 +2211,13 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
float y_scale_inv = invert ? -scale_y : scale_y; float y_scale_inv = invert ? -scale_y : scale_y;
stbtt__edge *e; stbtt__edge *e;
int n,i,j,k,m; int n,i,j,k,m;
#if STBTT_RASTERIZER_VERSION == 1
int vsubsample = result->h < 8 ? 15 : 5; int vsubsample = result->h < 8 ? 15 : 5;
#elif STBTT_RASTERIZER_VERSION == 2
int vsubsample = 1;
#else
#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
#endif
// vsubsample should divide 255 evenly; otherwise we won't reach full opacity // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
// now we have to blow out the windings into explicit edge lists // now we have to blow out the windings into explicit edge lists
@ -1786,7 +2254,8 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
} }
// now sort the edges by their highest point (should snap to integer, and then by x) // now sort the edges by their highest point (should snap to integer, and then by x)
STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
stbtt__sort_edges(e, n);
// now, traverse the scanlines and find the intersections on each scanline, use xor winding rule // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);

View File

@ -1,4 +1,4 @@
// stb_voxel_render.h - v0.80 - Sean Barrett, 2015 - public domain // stb_voxel_render.h - v0.81 - Sean Barrett, 2015 - public domain
// //
// This library helps render large-scale "voxel" worlds for games, // This library helps render large-scale "voxel" worlds for games,
// in this case, one with blocks that can have textures and that // in this case, one with blocks that can have textures and that
@ -190,7 +190,8 @@
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 0.81 (2015-04-12) added input.packed_compact to store rot, vheight & texlerp efficiently // 0.82 (2015-08-01) added input.packed_compact to store rot, vheight & texlerp efficiently
// 0.81 (2015-05-28) fix broken STBVOX_CONFIG_OPTIMIZED_VHEIGHT
// 0.80 (2015-04-11) fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING refactoring // 0.80 (2015-04-11) fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING refactoring
// change STBVOX_MAKE_LIGHTING to STBVOX_MAKE_LIGHTING_EXT so // change STBVOX_MAKE_LIGHTING to STBVOX_MAKE_LIGHTING_EXT so
// that header defs don't need to see config vars // that header defs don't need to see config vars
@ -2813,7 +2814,6 @@ void stbvox_make_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int fac
} }
} }
#ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
// get opposite-facing normal & texgen for opposite face, used to map up-facing vheight data to down-facing data // get opposite-facing normal & texgen for opposite face, used to map up-facing vheight data to down-facing data
static unsigned char stbvox_reverse_face[STBVF_count] = static unsigned char stbvox_reverse_face[STBVF_count] =
{ {
@ -2823,7 +2823,7 @@ static unsigned char stbvox_reverse_face[STBVF_count] =
0, 0, 0, 0, STBVF_ne_d, STBVF_ne_d, STBVF_nd, STBVF_nu 0, 0, 0, 0, STBVF_ne_d, STBVF_ne_d, STBVF_nd, STBVF_nu
}; };
#ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
// render non-planar quads by splitting into two triangles, rendering each as a degenerate quad // render non-planar quads by splitting into two triangles, rendering each as a degenerate quad
static void stbvox_make_12_split_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, unsigned char *ht) static void stbvox_make_12_split_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, unsigned char *ht)
{ {

View File

@ -1,7 +1,8 @@
// stretchy_buffer.h - v1.01 - public domain - nothings.org/stb // stretchy_buffer.h - v1.02 - public domain - nothings.org/stb
// a vector<>-like dynamic array for C // a vector<>-like dynamic array for C
// //
// version history: // version history:
// 1.02 - compiles as C++, but untested
// 1.01 - added a "common uses" documentation section // 1.01 - added a "common uses" documentation section
// 1.0 - fixed bug in the version I posted prematurely // 1.0 - fixed bug in the version I posted prematurely
// 0.9 - rewrite to try to avoid strict-aliasing optimization // 0.9 - rewrite to try to avoid strict-aliasing optimization
@ -193,7 +194,7 @@ static void * stb__sbgrowf(void *arr, int increment, int itemsize)
int dbl_cur = arr ? 2*stb__sbm(arr) : 0; int dbl_cur = arr ? 2*stb__sbm(arr) : 0;
int min_needed = stb_sb_count(arr) + increment; int min_needed = stb_sb_count(arr) + increment;
int m = dbl_cur > min_needed ? dbl_cur : min_needed; int m = dbl_cur > min_needed ? dbl_cur : min_needed;
int *p = realloc(arr ? stb__sbraw(arr) : 0, itemsize * m + sizeof(int)*2); int *p = (int *) realloc(arr ? stb__sbraw(arr) : 0, itemsize * m + sizeof(int)*2);
if (p) { if (p) {
if (!arr) if (!arr)
p[1] = 0; p[1] = 0;

View File

@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "TT_TEST" /FR /FD /GZ /c # ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "VORBIS_TEST" /FR /FD /GZ /c
# SUBTRACT CPP /YX # SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG"
@ -150,6 +150,10 @@ SOURCE=..\stb_vorbis.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\stb_voxel_render.h
# End Source File
# Begin Source File
SOURCE=..\stretchy_buffer.h SOURCE=..\stretchy_buffer.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -80,4 +80,3 @@ int main(int argc, char **argv)
} }
return 0; return 0;
} }

View File

@ -8,7 +8,6 @@
#define STB_HERRINGBONE_WANG_TILE_IMPLEMENTATION #define STB_HERRINGBONE_WANG_TILE_IMPLEMENTATION
#define STB_RECT_PACK_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION
#define STB_VOXEL_RENDER_IMPLEMENTATION #define STB_VOXEL_RENDER_IMPLEMENTATION
#define STBVOX_CONFIG_MODE 1
#define STBI_MALLOC my_malloc #define STBI_MALLOC my_malloc
#define STBI_FREE my_free #define STBI_FREE my_free
@ -27,9 +26,112 @@ void my_free(void *) { }
#include "stb_c_lexer.h" #include "stb_c_lexer.h"
#include "stb_divide.h" #include "stb_divide.h"
#include "stb_herringbone_wang_tile.h" #include "stb_herringbone_wang_tile.h"
#define STBVOX_CONFIG_MODE 1
#include "stb_voxel_render.h" #include "stb_voxel_render.h"
#define STBTE_DRAW_RECT(x0,y0,x1,y1,color) do ; while(0) #define STBTE_DRAW_RECT(x0,y0,x1,y1,color) do ; while(0)
#define STBTE_DRAW_TILE(x,y,id,highlight,data) do ; while(0) #define STBTE_DRAW_TILE(x,y,id,highlight,data) do ; while(0)
#define STB_TILEMAP_EDITOR_IMPLEMENTATION #define STB_TILEMAP_EDITOR_IMPLEMENTATION
#include "stb_tilemap_editor.h" #include "stb_tilemap_editor.h"
#include "stb_easy_font.h"
#define STB_LEAKCHECK_IMPLEMENTATION
#include "stb_leakcheck.h"
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"
#include "stretchy_buffer.h"
////////////////////////////////////////////////////////////
//
// text edit
#include <stdlib.h>
#include <string.h> // memmove
#include <ctype.h> // isspace
#define STB_TEXTEDIT_CHARTYPE char
#define STB_TEXTEDIT_STRING text_control
// get the base type
#include "stb_textedit.h"
// define our editor structure
typedef struct
{
char *string;
int stringlen;
STB_TexteditState state;
} text_control;
// define the functions we need
void layout_func(StbTexteditRow *row, STB_TEXTEDIT_STRING *str, int start_i)
{
int remaining_chars = str->stringlen - start_i;
row->num_chars = remaining_chars > 20 ? 20 : remaining_chars; // should do real word wrap here
row->x0 = 0;
row->x1 = 20; // need to account for actual size of characters
row->baseline_y_delta = 1.25;
row->ymin = -1;
row->ymax = 0;
}
int delete_chars(STB_TEXTEDIT_STRING *str, int pos, int num)
{
memmove(&str->string[pos], &str->string[pos+num], str->stringlen - (pos+num));
str->stringlen -= num;
return 1; // always succeeds
}
int insert_chars(STB_TEXTEDIT_STRING *str, int pos, STB_TEXTEDIT_CHARTYPE *newtext, int num)
{
str->string = (char *) realloc(str->string, str->stringlen + num);
memmove(&str->string[pos+num], &str->string[pos], str->stringlen - pos);
memcpy(&str->string[pos], newtext, num);
str->stringlen += num;
return 1; // always succeeds
}
// define all the #defines needed
#define KEYDOWN_BIT 0x80000000
#define STB_TEXTEDIT_STRINGLEN(tc) ((tc)->stringlen)
#define STB_TEXTEDIT_LAYOUTROW layout_func
#define STB_TEXTEDIT_GETWIDTH(tc,n,i) (1) // quick hack for monospaced
#define STB_TEXTEDIT_KEYTOTEXT(key) (((key) & KEYDOWN_BIT) ? 0 : (key))
#define STB_TEXTEDIT_GETCHAR(tc,i) ((tc)->string[i])
#define STB_TEXTEDIT_NEWLINE '\n'
#define STB_TEXTEDIT_IS_SPACE(ch) isspace(ch)
#define STB_TEXTEDIT_DELETECHARS delete_chars
#define STB_TEXTEDIT_INSERTCHARS insert_chars
#define STB_TEXTEDIT_K_SHIFT 0x40000000
#define STB_TEXTEDIT_K_CONTROL 0x20000000
#define STB_TEXTEDIT_K_LEFT (KEYDOWN_BIT | 1) // actually use VK_LEFT, SDLK_LEFT, etc
#define STB_TEXTEDIT_K_RIGHT (KEYDOWN_BIT | 2) // VK_RIGHT
#define STB_TEXTEDIT_K_UP (KEYDOWN_BIT | 3) // VK_UP
#define STB_TEXTEDIT_K_DOWN (KEYDOWN_BIT | 4) // VK_DOWN
#define STB_TEXTEDIT_K_LINESTART (KEYDOWN_BIT | 5) // VK_HOME
#define STB_TEXTEDIT_K_LINEEND (KEYDOWN_BIT | 6) // VK_END
#define STB_TEXTEDIT_K_TEXTSTART (STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_CONTROL)
#define STB_TEXTEDIT_K_TEXTEND (STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_CONTROL)
#define STB_TEXTEDIT_K_DELETE (KEYDOWN_BIT | 7) // VK_DELETE
#define STB_TEXTEDIT_K_BACKSPACE (KEYDOWN_BIT | 8) // VK_BACKSPACE
#define STB_TEXTEDIT_K_UNDO (KEYDOWN_BIT | STB_TEXTEDIT_K_CONTROL | 'z')
#define STB_TEXTEDIT_K_REDO (KEYDOWN_BIT | STB_TEXTEDIT_K_CONTROL | 'y')
#define STB_TEXTEDIT_K_INSERT (KEYDOWN_BIT | 9) // VK_INSERT
#define STB_TEXTEDIT_K_WORDLEFT (STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_CONTROL)
#define STB_TEXTEDIT_K_WORDRIGHT (STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_CONTROL)
#define STB_TEXTEDIT_K_PGUP (KEYDOWN_BIT | 10) // VK_PGUP -- not implemented
#define STB_TEXTEDIT_K_PGDOWN (KEYDOWN_BIT | 11) // VK_PGDOWN -- not implemented
#define STB_TEXTEDIT_IMPLEMENTATION
#include "stb_textedit.h"

View File

@ -8,11 +8,10 @@ extern void stb_vorbis_dumpmem(void);
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
size_t memlen; size_t memlen;
unsigned char *mem = stb_fileu("c:/x/01.ogg", &memlen); unsigned char *mem = stb_fileu("c:/x/theme_03.ogg", &memlen);
int chan, samplerate; int chan, samplerate;
short *output; short *output;
int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output); int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output);
stb_vorbis_dumpmem();
return 0; return 0;
} }
#endif #endif

View File

@ -20,6 +20,17 @@ attribution requirement). They may be less featureful, slower,
and/or use more memory. If you're already using an equivalent and/or use more memory. If you're already using an equivalent
library, there's probably no good reason to switch. library, there's probably no good reason to switch.
#### Why do you list "lines of code"? It's a terrible metric.
Just to give you some idea of the internal complexity of the library,
to help you manage your expectations, or to let you know what you're
getting into. While not all the libraries are written in the same
style, they're certainly similar styles, and so comparisons between
the libraries are probably still meaningful.
Note though that the lines do include both the implementation, the
part that corresponds to a header file, and the documentation.
#### Why single-file headers? #### Why single-file headers?
Windows doesn't have standard directories where libraries Windows doesn't have standard directories where libraries
@ -27,12 +38,21 @@ live. That makes deploying libraries in Windows a lot more
painful than open source developers on Unix-derivates generally painful than open source developers on Unix-derivates generally
realize. (It also makes library dependencies a lot worse in Windows.) realize. (It also makes library dependencies a lot worse in Windows.)
There's also a common problem in Windows where a library was built
against a different version of the runtime library, which causes
link conflicts and confusion. Shipping the libs as headers means
you normally just compile them straight into your project without
making libraries, thus sidestepping that problem.
Making them a single file makes it very easy to just Making them a single file makes it very easy to just
drop them into a project that needs them. (Of course you can drop them into a project that needs them. (Of course you can
still put them in a proper shared library tree if you want.) still put them in a proper shared library tree if you want.)
Why not two files, one a header and one an implementation?
The difference between 10 files and 9 files is not a big deal, The difference between 10 files and 9 files is not a big deal,
but the difference between 2 files and 1 file is a big deal. but the difference between 2 files and 1 file is a big deal.
You don't need to zip or tar the files up, you don't have to
remember to attach *two* files, etc.
#### Why "stb"? Is this something to do with Set-Top Boxes? #### Why "stb"? Is this something to do with Set-Top Boxes?
@ -58,12 +78,9 @@ Yes. https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
#### Why public domain? #### Why public domain?
Because more people will use it. Because it's not viral, people I prefer it over GPL, LGPL, BSD, zlib, etc. for many reasons.
are not obligated to give back, so you could argue that it hurts Some of them are listed here:
the *development* of it, and then because it doesn't develop as https://github.com/nothings/stb/blob/master/docs/why_public_domain.md
well it's not as good, and then because it's not as good, in the
long run maybe fewer people will use it. I have total respect for
that opinion, but I just don't believe it myself for most software.
#### Why C? #### Why C?

View File

@ -3,5 +3,5 @@ stb
single-file public domain libraries for C/C++ single-file public domain libraries for C/C++
library | lastest version | category | description library | lastest version | category | LoC | description
--------------------- | ---- | -------- | -------------------------------- --------------------- | ---- | -------- | --- | --------------------------------

View File

@ -10,8 +10,8 @@ stb_voxel_render.h | 3D graphics | Minecraft-esque voxel rendering
stb_dxt.h | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor stb_dxt.h | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor
stb_perlin.h | 3D graphics | revised Perlin noise (3D input, 1D output) stb_perlin.h | 3D graphics | revised Perlin noise (3D input, 1D output)
stb_easy_font.h | 3D graphics | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc stb_easy_font.h | 3D graphics | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
stb_tilemap_editor.h | game development | embeddable tilemap editor stb_tilemap_editor.h | game dev | embeddable tilemap editor
stb_herringbone_wang_tile.h | game development | herringbone Wang tile map generator stb_herringbone_wang_tile.h | game dev | herringbone Wang tile map generator
stb_c_lexer.h | parsing | simplify writing parsers for C-like languages stb_c_lexer.h | parsing | simplify writing parsers for C-like languages
stb_divide.h | math | more useful 32-bit modulus e.g. "euclidean divide" stb_divide.h | math | more useful 32-bit modulus e.g. "euclidean divide"
stb.h | misc | helper functions for C, mostly redundant in C++; basically author's personal stuff stb.h | misc | helper functions for C, mostly redundant in C++; basically author's personal stuff

View File

@ -4,23 +4,23 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i; int i;
int hlen, flen, listlen; int hlen, flen, listlen, total_lines = 0;
char *header = stb_file("README.header.md", &hlen); // stb_file - read file into malloc()ed buffer char *header = stb_file("README.header.md", &hlen); // stb_file - read file into malloc()ed buffer
char *footer = stb_file("README.footer.md", &flen); // stb_file - read file into malloc()ed buffer char *footer = stb_file("README.footer.md", &flen); // stb_file - read file into malloc()ed buffer
char **list = stb_stringfile("README.list", &listlen); // stb_stringfile - read file lines into malloced array of strings char **list = stb_stringfile("README.list", &listlen); // stb_stringfile - read file lines into malloced array of strings
FILE *f = fopen("../README.md", "wb"); FILE *f = fopen("../README.md", "wb");
fprintf(f, "<!--- THIS FILE IS AUTOMATICALLY GENERATED, DO NOT CHANGE IT BY HAND --->\n\n");
fwrite(header, 1, hlen, f); fwrite(header, 1, hlen, f);
for (i=0; i < listlen; ++i) { for (i=0; i < listlen; ++i) {
int num,j; int num,j;
char **tokens = stb_tokens_stripwhite(list[i], "|", &num); // stb_tokens -- tokenize string into malloced array of strings char **tokens = stb_tokens_stripwhite(list[i], "|", &num); // stb_tokens -- tokenize string into malloced array of strings
FILE *g = fopen(stb_sprintf("../%s", tokens[0]), "rb"); // stb_sprintf -- sprintf to a static temp buffer (not threadsafe or secure) int num_lines;
char buffer[256], *s1, *s2; char **lines = stb_stringfile(stb_sprintf("../%s", tokens[0]), &num_lines);
fread(buffer, 1, 256, g); char *s1, *s2,*s3;
fclose(g); s1 = strchr(lines[0], '-');
buffer[255] = 0;
s1 = strchr(buffer, '-');
if (!s1) stb_fatal("Couldn't find '-' before version number in %s", tokens[0]); // stb_fatal -- print error message & exit if (!s1) stb_fatal("Couldn't find '-' before version number in %s", tokens[0]); // stb_fatal -- print error message & exit
s2 = strchr(s1+2, '-'); s2 = strchr(s1+2, '-');
if (!s2) stb_fatal("Couldn't find '-' after version number in %s", tokens[0]); // stb_fatal -- print error message & exit if (!s2) stb_fatal("Couldn't find '-' after version number in %s", tokens[0]); // stb_fatal -- print error message & exit
@ -28,16 +28,32 @@ int main(int argc, char **argv)
s1 += 1; s1 += 1;
s1 = stb_trimwhite(s1); // stb_trimwhite -- advance pointer to after whitespace & delete trailing whitespace s1 = stb_trimwhite(s1); // stb_trimwhite -- advance pointer to after whitespace & delete trailing whitespace
if (*s1 == 'v') ++s1; if (*s1 == 'v') ++s1;
fprintf(f, "**%s** | %s", tokens[0], s1); s3 = tokens[0];
stb_trimwhite(s3);
if (strlen(s3) < 21) {
fprintf(f, "**%s** | %s", tokens[0], s1);
} else {
char buffer[256];
strncpy(buffer, s3, 18);
buffer[18] = 0;
strcat(buffer, "...");
fprintf(f, "**%s** | %s", buffer, s1);
}
s1 = stb_trimwhite(tokens[1]); // stb_trimwhite -- advance pointer to after whitespace & delete trailing whitespace s1 = stb_trimwhite(tokens[1]); // stb_trimwhite -- advance pointer to after whitespace & delete trailing whitespace
s2 = stb_dupreplace(s1, " ", "&nbsp;"); // stb_dupreplace -- search & replace string and malloc result s2 = stb_dupreplace(s1, " ", "&nbsp;"); // stb_dupreplace -- search & replace string and malloc result
fprintf(f, " | %s", s2); fprintf(f, " | %s", s2);
free(s2); free(s2);
fprintf(f, " | %d", num_lines);
total_lines += num_lines;
for (j=2; j < num; ++j) for (j=2; j < num; ++j)
fprintf(f, " | %s", tokens[j]); fprintf(f, " | %s", tokens[j]);
fprintf(f, "\n"); fprintf(f, "\n");
} }
fprintf(f, "\n");
fprintf(f, "Total libraries: %d \n", listlen);
fprintf(f, "Total lines of C code: %d\n\n", total_lines);
fwrite(footer, 1, flen, f); fwrite(footer, 1, flen, f);
fclose(f); fclose(f);

View File

@ -87,6 +87,10 @@ SOURCE=.\make_readme.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\README.header.md
# End Source File
# Begin Source File
SOURCE=.\README.list SOURCE=.\README.list
# End Source File # End Source File
# End Target # End Target