Merge branch 'master' into working
Conflicts: stb_voxel_render.h
This commit is contained in:
commit
d821fd83f3
75
README.md
75
README.md
@ -1,28 +1,34 @@
|
||||
<!--- THIS FILE IS AUTOMATICALLY GENERATED, DO NOT CHANGE IT BY HAND --->
|
||||
|
||||
stb
|
||||
===
|
||||
|
||||
single-file public domain libraries for C/C++
|
||||
|
||||
library | lastest version | category | description
|
||||
--------------------- | ---- | -------- | --------------------------------
|
||||
**stb_vorbis.c** | 1.04 | audio | 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_truetype.h** | 1.03 | graphics | parse, decode, and rasterize characters from truetype fonts
|
||||
**stb_image_write.h** | 0.98 | graphics | image writing to disk: PNG, TGA, BMP
|
||||
**stb_image_resize.h** | 0.90 | graphics | resize images larger/smaller with good quality
|
||||
**stb_rect_pack.h** | 0.05 | graphics | 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++
|
||||
**stb_textedit.h** | 1.5 | UI | guts of a text editor for games etc implementing them from scratch
|
||||
**stb_voxel_render.h** | 0.80 | 3D graphics | Minecraft-esque voxel rendering "engine" with many more features
|
||||
**stb_dxt.h** | 1.04 | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor
|
||||
**stb_perlin.h** | 0.2 | 3D graphics | revised Perlin noise (3D input, 1D output)
|
||||
**stb_easy_font.h** | 0.5 | 3D graphics | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
|
||||
**stb_tilemap_editor.h** | 0.30 | game development | embeddable tilemap editor
|
||||
**stb_herringbone_wang_tile.h** | 0.6 | game development | herringbone Wang tile map generator
|
||||
**stb_c_lexer.h** | 0.06 | parsing | simplify writing parsers for C-like languages
|
||||
**stb_divide.h** | 0.91 | math | 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_leakcheck.h** | 0.1 | misc | quick-and-dirty malloc/free leak-checking
|
||||
library | lastest version | category | LoC | description
|
||||
--------------------- | ---- | -------- | --- | --------------------------------
|
||||
**stb_vorbis.c** | 1.05 | audio | 5445 | decode ogg vorbis files from file/memory to float/16-bit signed output
|
||||
**stb_image.h** | 2.06 | graphics | 6437 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
|
||||
**stb_truetype.h** | 1.06 | graphics | 2632 | parse, decode, and rasterize characters from truetype fonts
|
||||
**stb_image_write.h** | 0.98 | graphics | 730 | image writing to disk: PNG, TGA, BMP
|
||||
**stb_image_resize.h** | 0.90 | graphics | 2585 | resize images larger/smaller with good quality
|
||||
**stb_rect_pack.h** | 0.06 | graphics | 560 | simple 2D rectangle packer with decent quality
|
||||
**stretchy_buffer.h** | 1.02 | utility | 210 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++
|
||||
**stb_textedit.h** | 1.6 | UI | 1290 | guts of a text editor for games etc implementing them from scratch
|
||||
**stb_voxel_render.h** | 0.81 | 3D graphics | 3644 | Minecraft-esque voxel rendering "engine" with many more features
|
||||
**stb_dxt.h** | 1.04 | 3D graphics | 624 | Fabian "ryg" Giesen's real-time DXT compressor
|
||||
**stb_perlin.h** | 0.2 | 3D graphics | 175 | revised Perlin noise (3D input, 1D output)
|
||||
**stb_easy_font.h** | 0.5 | 3D graphics | 220 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
|
||||
**stb_tilemap_editor.h** | 0.35 | game dev | 4120 | embeddable tilemap editor
|
||||
**stb_herringbone_wa...** | 0.6 | game dev | 1217 | herringbone Wang tile map generator
|
||||
**stb_c_lexer.h** | 0.06 | parsing | 809 | simplify writing parsers for C-like languages
|
||||
**stb_divide.h** | 0.91 | math | 373 | more useful 32-bit modulus e.g. "euclidean divide"
|
||||
**stb.h** | 2.24 | misc | 14086 | helper functions for C, mostly redundant in C++; basically author's personal stuff
|
||||
**stb_leakcheck.h** | 0.2 | misc | 117 | quick-and-dirty malloc/free leak-checking
|
||||
|
||||
Total libraries: 18
|
||||
Total lines of C code: 45274
|
||||
|
||||
|
||||
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
|
||||
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?
|
||||
|
||||
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
|
||||
realize. (It also makes library dependencies a lot worse in Windows.)
|
||||
|
||||
There's also a common problem in Windows where a library was built
|
||||
against a different version of the runtime library, which causes
|
||||
link conflicts and confusion. Shipping the libs as headers means
|
||||
you normally just compile them straight into your project without
|
||||
making libraries, thus sidestepping that problem.
|
||||
|
||||
Making them a single file makes it very easy to just
|
||||
drop them into a project that needs them. (Of course you can
|
||||
still put them in a proper shared library tree if you want.)
|
||||
|
||||
Why not two files, one a header and one an implementation?
|
||||
The difference between 10 files and 9 files is not a big deal,
|
||||
but the difference between 2 files and 1 file is a big deal.
|
||||
You don't need to zip or tar the files up, you don't have to
|
||||
remember to attach *two* files, etc.
|
||||
|
||||
#### Why "stb"? Is this something to do with Set-Top Boxes?
|
||||
|
||||
@ -83,12 +109,9 @@ Yes. https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
|
||||
|
||||
#### Why 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.
|
||||
I prefer it over GPL, LGPL, BSD, zlib, etc. for many reasons.
|
||||
Some of them are listed here:
|
||||
https://github.com/nothings/stb/blob/master/docs/why_public_domain.md
|
||||
|
||||
#### Why C?
|
||||
|
||||
|
116
docs/why_public_domain.md
Normal file
116
docs/why_public_domain.md
Normal 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
2
stb.h
@ -5255,7 +5255,7 @@ int stb_fullpath(char *abs, int abs_size, char *rel)
|
||||
#ifdef _MSC_VER
|
||||
return _fullpath(abs, rel, abs_size) != NULL;
|
||||
#else
|
||||
if (abs[0] == '/' || abs[0] == '~') {
|
||||
if (rel[0] == '/' || rel[0] == '~') {
|
||||
if ((int) strlen(rel) >= abs_size)
|
||||
return 0;
|
||||
strcpy(abs,rel);
|
||||
|
47
stb_image.h
47
stb_image.h
@ -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
|
||||
|
||||
Do this:
|
||||
@ -143,6 +143,9 @@
|
||||
|
||||
|
||||
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
|
||||
stbi_set_flip_vertically_on_load
|
||||
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)
|
||||
optimize PNG
|
||||
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.
|
||||
|
||||
@ -633,11 +634,14 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
|
||||
#endif
|
||||
|
||||
// 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
|
||||
#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,
|
||||
// (but compiling with -msse2 allows the compiler to use SSE2 everywhere;
|
||||
// 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
|
||||
|
||||
#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
|
||||
// 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
|
||||
@ -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
|
||||
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];
|
||||
k &= stbi__bmask[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)
|
||||
j->eob_run += stbi__jpeg_get_bits(j, r);
|
||||
r = 64; // force end of block
|
||||
} else
|
||||
r = 16; // r=15 is the code for 16 0s
|
||||
} else {
|
||||
// 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 {
|
||||
if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
|
||||
// sign bit
|
||||
@ -1859,7 +1868,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
|
||||
|
||||
// advance by r
|
||||
while (k <= j->spec_end) {
|
||||
short *p = &data[stbi__jpeg_dezigzag[k]];
|
||||
short *p = &data[stbi__jpeg_dezigzag[k++]];
|
||||
if (*p != 0) {
|
||||
if (stbi__jpeg_get_bit(j))
|
||||
if ((*p & bit)==0) {
|
||||
@ -1868,15 +1877,12 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
|
||||
else
|
||||
*p -= bit;
|
||||
}
|
||||
++k;
|
||||
} else {
|
||||
if (r == 0) {
|
||||
if (s)
|
||||
data[stbi__jpeg_dezigzag[k++]] = (short) s;
|
||||
*p = (short) s;
|
||||
break;
|
||||
}
|
||||
--r;
|
||||
++k;
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
if (channel >= channelCount) {
|
||||
// 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 {
|
||||
// Read the RLE data.
|
||||
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;
|
||||
if (channel > channelCount) {
|
||||
// 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 {
|
||||
// Read the data.
|
||||
for (i = 0; i < pixelCount; i++)
|
||||
*p = stbi__get8(s), p += 4;
|
||||
for (i = 0; i < pixelCount; i++, 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 (comp) *comp = channelCount;
|
||||
if (comp) *comp = 4;
|
||||
*y = h;
|
||||
*x = w;
|
||||
|
||||
@ -6287,6 +6295,9 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
|
||||
|
||||
/*
|
||||
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)
|
||||
stbi_set_flip_vertically_on_load (nguillemot)
|
||||
fix NEON support; fix mingw support
|
||||
|
@ -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
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
mi->file = file;
|
||||
mi->line = line;
|
||||
|
@ -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
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
@ -13,6 +13,7 @@
|
||||
// More docs to come.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
@ -20,8 +21,18 @@
|
||||
// implement them to the same API, but with a different init
|
||||
// function.
|
||||
//
|
||||
// Credits
|
||||
//
|
||||
// Library
|
||||
// Sean Barrett
|
||||
// Minor features
|
||||
// Martins Mozeiko
|
||||
// Bugfixes / warning fixes
|
||||
// [your name could be here]
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||
// 0.01: initial release
|
||||
@ -169,7 +180,10 @@ struct stbrp_context
|
||||
//
|
||||
|
||||
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||
#ifndef STBRP_SORT
|
||||
#include <stdlib.h>
|
||||
#define STBRP_SORT qsort
|
||||
#endif
|
||||
|
||||
#ifndef STBRP_ASSERT
|
||||
#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
|
||||
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) {
|
||||
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
|
||||
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
|
||||
for (i=0; i < num_rects; ++i)
|
||||
|
@ -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
|
||||
//
|
||||
// This C header file implements the guts of a multi-line text-editing
|
||||
@ -24,12 +24,14 @@
|
||||
//
|
||||
// DEPENDENCIES
|
||||
//
|
||||
// Uses the C runtime function 'memmove'. Uses no other functions.
|
||||
// Performs no runtime allocations.
|
||||
// Uses the C runtime function 'memmove', which you can override
|
||||
// by defining STB_TEXTEDIT_memmove before the implementation.
|
||||
// Uses no other functions. Performs no runtime allocations.
|
||||
//
|
||||
//
|
||||
// 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.4 (2014-08-17) fix signed/unsigned warnings
|
||||
// 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
|
||||
// Scott Graham: mouse selection bugfix in 1.3
|
||||
// Fabian Giesen: secondary key inputs in 1.5
|
||||
// Martins Mozeiko: STB_TEXTEDIT_memmove
|
||||
//
|
||||
// USAGE
|
||||
//
|
||||
@ -358,7 +361,10 @@ typedef struct
|
||||
// included just the "header" portion
|
||||
#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;
|
||||
// delete n characters from all other records
|
||||
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)
|
||||
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_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;
|
||||
// delete n characters from all other records
|
||||
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)
|
||||
if (state->undo_rec[i].char_storage >= 0)
|
||||
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
|
||||
}
|
||||
++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])));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
//
|
||||
// Embeddable tilemap editor for C/C++
|
||||
@ -275,6 +275,10 @@
|
||||
// either approach allows cut&pasting between levels.)
|
||||
//
|
||||
// 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
|
||||
// - properties panel for editing user-defined "object" properties
|
||||
// - can link each tile to one other tile
|
||||
@ -296,11 +300,16 @@
|
||||
// Support STBTE_HITTEST_TILE above
|
||||
// ?Cancel drags by clicking other button? - may be fixed
|
||||
// Finish support for toolbar at side
|
||||
// Layer name buttons grow to fill box
|
||||
//
|
||||
// CREDITS
|
||||
//
|
||||
// Written by Sean Barrett, September & October 2014.
|
||||
//
|
||||
// Main editor & features
|
||||
// Sean Barrett
|
||||
// Additional features:
|
||||
// Josh Huelsman
|
||||
// Bugfixes:
|
||||
// [this could be you!]
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
@ -339,7 +348,7 @@ enum
|
||||
// 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
|
||||
// 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
|
||||
@ -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);
|
||||
// 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
|
||||
// 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)
|
||||
@ -938,6 +947,7 @@ struct stbte_tilemap
|
||||
int tileinfo_dirty;
|
||||
stbte__layer layerinfo[STBTE_MAX_LAYERS];
|
||||
int has_layer_names;
|
||||
int layername_width;
|
||||
int layer_scroll;
|
||||
int propmode;
|
||||
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->propmode = 0;
|
||||
tm->has_layer_names = 0;
|
||||
tm->layername_width = 0;
|
||||
tm->undo_available_valid = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int stbte__text_width(const char *str);
|
||||
|
||||
void stbte_set_layername(stbte_tilemap *tm, int layer, const char *layername)
|
||||
{
|
||||
STBTE_ASSERT(layer >= 0 && layer < tm->num_layers);
|
||||
if (layer >= 0 && layer < tm->num_layers) {
|
||||
int width;
|
||||
tm->layerinfo[layer].name = layername;
|
||||
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)
|
||||
{
|
||||
int i, y, n;
|
||||
int x1 = x0+w;
|
||||
int y1 = y0+h;
|
||||
int xoff = tm->has_layer_names ? 50 : 20;
|
||||
static char *propmodes[3] = {
|
||||
"default", "always", "never"
|
||||
};
|
||||
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;
|
||||
y0 += 5;
|
||||
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;
|
||||
stbte__draw_text(x0,y+2, "prop:", w, STBTE__TEXTCOLOR(STBTE__cpanel));
|
||||
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))
|
||||
tm->propmode = (tm->propmode+1)%3;
|
||||
#endif
|
||||
|
577
stb_truetype.h
577
stb_truetype.h
@ -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
|
||||
//
|
||||
// This library processes TrueType files:
|
||||
@ -38,12 +38,18 @@
|
||||
// Cap Petschulat
|
||||
// Omar Cornut
|
||||
// github:aloucks
|
||||
// Peter LaValle
|
||||
//
|
||||
// Misc other:
|
||||
// Ryan Gordon
|
||||
//
|
||||
// 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.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
|
||||
@ -117,6 +123,15 @@
|
||||
// stbtt_GetFontVMetrics()
|
||||
// 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
|
||||
//
|
||||
// Immediately after this block comment are a series of sample programs.
|
||||
@ -216,7 +231,15 @@
|
||||
// Baked bitmap interface 70 LOC /
|
||||
// Font name matching & access 150 LOC ---- 150
|
||||
// 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)
|
||||
{
|
||||
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
|
||||
glGenTextures(1, &ftex);
|
||||
glBindTexture(GL_TEXTURE_2D, ftex);
|
||||
@ -327,7 +350,7 @@ int main(int arg, char **argv)
|
||||
stbtt_fontinfo font;
|
||||
int i,j,ascent,baseline,ch=0;
|
||||
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"));
|
||||
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_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
|
||||
#ifndef STBTT_ifloor
|
||||
#include <math.h>
|
||||
@ -443,6 +454,12 @@ int main(int arg, char **argv)
|
||||
#ifndef __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
|
||||
extern "C" {
|
||||
#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];
|
||||
|
||||
#ifndef STBTT_RASTERIZER_VERSION
|
||||
#define STBTT_RASTERIZER_VERSION 2
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 {
|
||||
float x0,y0, x1,y1;
|
||||
int invert;
|
||||
} stbtt__edge;
|
||||
|
||||
|
||||
typedef struct stbtt__active_edge
|
||||
{
|
||||
struct stbtt__active_edge *next;
|
||||
#if STBTT_RASTERIZER_VERSION==1
|
||||
int x,dx;
|
||||
float ey;
|
||||
struct stbtt__active_edge *next;
|
||||
int valid;
|
||||
int direction;
|
||||
#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;
|
||||
|
||||
#define FIXSHIFT 10
|
||||
#define FIX (1 << FIXSHIFT)
|
||||
#define FIXMASK (FIX-1)
|
||||
#if STBTT_RASTERIZER_VERSION == 1
|
||||
#define STBTT_FIXSHIFT 10
|
||||
#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);
|
||||
STBTT_assert(e->y0 <= start_point);
|
||||
if (!z) return z;
|
||||
// round dx down to avoid going too far
|
||||
|
||||
// round dx down to avoid overshooting
|
||||
if (dxdy < 0)
|
||||
z->dx = -STBTT_ifloor(FIX * -dxdy);
|
||||
z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
|
||||
else
|
||||
z->dx = STBTT_ifloor(FIX * dxdy);
|
||||
z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
|
||||
z->x -= off_x * FIX;
|
||||
z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
|
||||
|
||||
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->next = 0;
|
||||
z->valid = e->invert ? 1 : -1;
|
||||
z->direction = e->invert ? 1 : -1;
|
||||
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
|
||||
// wouldn't happen, but it could happen if the truetype glyph bounding boxes
|
||||
// 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) {
|
||||
if (w == 0) {
|
||||
// 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 {
|
||||
int x1 = e->x; w += e->valid;
|
||||
int x1 = e->x; w += e->direction;
|
||||
// if we went to zero, we need to draw
|
||||
if (w == 0) {
|
||||
int i = x0 >> FIXSHIFT;
|
||||
int j = x1 >> FIXSHIFT;
|
||||
int i = x0 >> STBTT_FIXSHIFT;
|
||||
int j = x1 >> STBTT_FIXSHIFT;
|
||||
|
||||
if (i < len && j >= 0) {
|
||||
if (i == j) {
|
||||
// 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 {
|
||||
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
|
||||
i = -1; // clip
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
stbtt__hheap hh = { 0 };
|
||||
stbtt__active_edge *active = NULL;
|
||||
int y,j=0;
|
||||
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;
|
||||
if (z->ey <= scan_y) {
|
||||
*step = z->next; // delete from list
|
||||
STBTT_assert(z->valid);
|
||||
z->valid = 0;
|
||||
STBTT_free(z, userdata);
|
||||
STBTT_assert(z->direction);
|
||||
z->direction = 0;
|
||||
stbtt__hheap_free(&hh, z);
|
||||
} else {
|
||||
z->x += z->dx; // advance to position for current scanline
|
||||
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
|
||||
while (e->y0 <= 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
|
||||
if (active == NULL)
|
||||
active = z;
|
||||
@ -1719,24 +1828,377 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
|
||||
++j;
|
||||
}
|
||||
|
||||
while (active) {
|
||||
stbtt__active_edge *z = active;
|
||||
active = active->next;
|
||||
STBTT_free(z, userdata);
|
||||
}
|
||||
stbtt__hheap_cleanup(&hh, userdata);
|
||||
|
||||
if (scanline != scanline_data)
|
||||
STBTT_free(scanline, userdata);
|
||||
}
|
||||
|
||||
static int stbtt__edge_compare(const void *p, const void *q)
|
||||
{
|
||||
stbtt__edge *a = (stbtt__edge *) p;
|
||||
stbtt__edge *b = (stbtt__edge *) q;
|
||||
#elif STBTT_RASTERIZER_VERSION == 2
|
||||
|
||||
if (a->y0 < b->y0) return -1;
|
||||
if (a->y0 > b->y0) return 1;
|
||||
return 0;
|
||||
// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
|
||||
// (i.e. it has already been clipped to those)
|
||||
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
|
||||
@ -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;
|
||||
stbtt__edge *e;
|
||||
int n,i,j,k,m;
|
||||
#if STBTT_RASTERIZER_VERSION == 1
|
||||
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
|
||||
|
||||
// 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)
|
||||
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
|
||||
stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
|
||||
|
@ -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,
|
||||
// in this case, one with blocks that can have textures and that
|
||||
@ -190,7 +190,8 @@
|
||||
//
|
||||
// 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
|
||||
// change STBVOX_MAKE_LIGHTING to STBVOX_MAKE_LIGHTING_EXT so
|
||||
// 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
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
#ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
|
||||
// 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)
|
||||
{
|
||||
|
@ -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
|
||||
//
|
||||
// version history:
|
||||
// 1.02 - compiles as C++, but untested
|
||||
// 1.01 - added a "common uses" documentation section
|
||||
// 1.0 - fixed bug in the version I posted prematurely
|
||||
// 0.9 - rewrite to try to avoid strict-aliasing optimization
|
||||
@ -193,7 +194,7 @@ static void * stb__sbgrowf(void *arr, int increment, int itemsize)
|
||||
int dbl_cur = arr ? 2*stb__sbm(arr) : 0;
|
||||
int min_needed = stb_sb_count(arr) + increment;
|
||||
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 (!arr)
|
||||
p[1] = 0;
|
||||
|
@ -66,7 +66,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "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
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
@ -150,6 +150,10 @@ SOURCE=..\stb_vorbis.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\stb_voxel_render.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\stretchy_buffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -80,4 +80,3 @@ int main(int argc, char **argv)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
#define STB_HERRINGBONE_WANG_TILE_IMPLEMENTATION
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#define STB_VOXEL_RENDER_IMPLEMENTATION
|
||||
#define STBVOX_CONFIG_MODE 1
|
||||
|
||||
#define STBI_MALLOC my_malloc
|
||||
#define STBI_FREE my_free
|
||||
@ -27,9 +26,112 @@ void my_free(void *) { }
|
||||
#include "stb_c_lexer.h"
|
||||
#include "stb_divide.h"
|
||||
#include "stb_herringbone_wang_tile.h"
|
||||
|
||||
#define STBVOX_CONFIG_MODE 1
|
||||
#include "stb_voxel_render.h"
|
||||
|
||||
#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 STB_TILEMAP_EDITOR_IMPLEMENTATION
|
||||
#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"
|
||||
|
||||
|
||||
|
@ -8,11 +8,10 @@ extern void stb_vorbis_dumpmem(void);
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
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;
|
||||
short *output;
|
||||
int samples = stb_vorbis_decode_memory(mem, memlen, &chan, &samplerate, &output);
|
||||
stb_vorbis_dumpmem();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -20,6 +20,17 @@ attribution requirement). They may be less featureful, slower,
|
||||
and/or use more memory. If you're already using an equivalent
|
||||
library, there's probably no good reason to switch.
|
||||
|
||||
#### Why do you list "lines of code"? It's a terrible metric.
|
||||
|
||||
Just to give you some idea of the internal complexity of the library,
|
||||
to help you manage your expectations, or to let you know what you're
|
||||
getting into. While not all the libraries are written in the same
|
||||
style, they're certainly similar styles, and so comparisons between
|
||||
the libraries are probably still meaningful.
|
||||
|
||||
Note though that the lines do include both the implementation, the
|
||||
part that corresponds to a header file, and the documentation.
|
||||
|
||||
#### Why single-file headers?
|
||||
|
||||
Windows doesn't have standard directories where libraries
|
||||
@ -27,12 +38,21 @@ live. That makes deploying libraries in Windows a lot more
|
||||
painful than open source developers on Unix-derivates generally
|
||||
realize. (It also makes library dependencies a lot worse in Windows.)
|
||||
|
||||
There's also a common problem in Windows where a library was built
|
||||
against a different version of the runtime library, which causes
|
||||
link conflicts and confusion. Shipping the libs as headers means
|
||||
you normally just compile them straight into your project without
|
||||
making libraries, thus sidestepping that problem.
|
||||
|
||||
Making them a single file makes it very easy to just
|
||||
drop them into a project that needs them. (Of course you can
|
||||
still put them in a proper shared library tree if you want.)
|
||||
|
||||
Why not two files, one a header and one an implementation?
|
||||
The difference between 10 files and 9 files is not a big deal,
|
||||
but the difference between 2 files and 1 file is a big deal.
|
||||
You don't need to zip or tar the files up, you don't have to
|
||||
remember to attach *two* files, etc.
|
||||
|
||||
#### Why "stb"? Is this something to do with Set-Top Boxes?
|
||||
|
||||
@ -58,12 +78,9 @@ Yes. https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
|
||||
|
||||
#### Why 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.
|
||||
I prefer it over GPL, LGPL, BSD, zlib, etc. for many reasons.
|
||||
Some of them are listed here:
|
||||
https://github.com/nothings/stb/blob/master/docs/why_public_domain.md
|
||||
|
||||
#### Why C?
|
||||
|
||||
|
@ -3,5 +3,5 @@ stb
|
||||
|
||||
single-file public domain libraries for C/C++
|
||||
|
||||
library | lastest version | category | description
|
||||
--------------------- | ---- | -------- | --------------------------------
|
||||
library | lastest version | category | LoC | description
|
||||
--------------------- | ---- | -------- | --- | --------------------------------
|
||||
|
@ -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_perlin.h | 3D graphics | revised Perlin noise (3D input, 1D output)
|
||||
stb_easy_font.h | 3D graphics | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
|
||||
stb_tilemap_editor.h | game development | embeddable tilemap editor
|
||||
stb_herringbone_wang_tile.h | game development | herringbone Wang tile map generator
|
||||
stb_tilemap_editor.h | game dev | embeddable tilemap editor
|
||||
stb_herringbone_wang_tile.h | game dev | herringbone Wang tile map generator
|
||||
stb_c_lexer.h | parsing | simplify writing parsers for C-like languages
|
||||
stb_divide.h | math | more useful 32-bit modulus e.g. "euclidean divide"
|
||||
stb.h | misc | helper functions for C, mostly redundant in C++; basically author's personal stuff
|
||||
|
@ -4,23 +4,23 @@
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
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 *footer = stb_file("README.footer.md", &flen); // stb_file - read file into malloc()ed buffer
|
||||
char **list = stb_stringfile("README.list", &listlen); // stb_stringfile - read file lines into malloced array of strings
|
||||
|
||||
FILE *f = fopen("../README.md", "wb");
|
||||
|
||||
fprintf(f, "<!--- THIS FILE IS AUTOMATICALLY GENERATED, DO NOT CHANGE IT BY HAND --->\n\n");
|
||||
fwrite(header, 1, hlen, f);
|
||||
|
||||
for (i=0; i < listlen; ++i) {
|
||||
int num,j;
|
||||
char **tokens = stb_tokens_stripwhite(list[i], "|", &num); // stb_tokens -- tokenize string into malloced array of strings
|
||||
FILE *g = fopen(stb_sprintf("../%s", tokens[0]), "rb"); // stb_sprintf -- sprintf to a static temp buffer (not threadsafe or secure)
|
||||
char buffer[256], *s1, *s2;
|
||||
fread(buffer, 1, 256, g);
|
||||
fclose(g);
|
||||
buffer[255] = 0;
|
||||
s1 = strchr(buffer, '-');
|
||||
int num_lines;
|
||||
char **lines = stb_stringfile(stb_sprintf("../%s", tokens[0]), &num_lines);
|
||||
char *s1, *s2,*s3;
|
||||
s1 = strchr(lines[0], '-');
|
||||
if (!s1) stb_fatal("Couldn't find '-' before version number in %s", tokens[0]); // stb_fatal -- print error message & exit
|
||||
s2 = strchr(s1+2, '-');
|
||||
if (!s2) stb_fatal("Couldn't find '-' after version number in %s", tokens[0]); // stb_fatal -- print error message & exit
|
||||
@ -28,16 +28,32 @@ int main(int argc, char **argv)
|
||||
s1 += 1;
|
||||
s1 = stb_trimwhite(s1); // stb_trimwhite -- advance pointer to after whitespace & delete trailing whitespace
|
||||
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
|
||||
s2 = stb_dupreplace(s1, " ", " "); // stb_dupreplace -- search & replace string and malloc result
|
||||
fprintf(f, " | %s", s2);
|
||||
free(s2);
|
||||
fprintf(f, " | %d", num_lines);
|
||||
total_lines += num_lines;
|
||||
for (j=2; j < num; ++j)
|
||||
fprintf(f, " | %s", tokens[j]);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
fprintf(f, "\n");
|
||||
fprintf(f, "Total libraries: %d \n", listlen);
|
||||
fprintf(f, "Total lines of C code: %d\n\n", total_lines);
|
||||
|
||||
fwrite(footer, 1, flen, f);
|
||||
fclose(f);
|
||||
|
||||
|
@ -87,6 +87,10 @@ SOURCE=.\make_readme.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\README.header.md
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\README.list
|
||||
# End Source File
|
||||
# End Target
|
||||
|
Loading…
Reference in New Issue
Block a user