Some maintenance
* moved all SoftLK source files to src/ * moved all external libraries to external/ * updated README
This commit is contained in:
parent
6a76767bb1
commit
542c1e4f9d
|
@ -39,8 +39,13 @@ SoftLK should work on any plattform that has a C compiler, SDL2 and OpenGL 2.1,
|
|||
|
||||
## Library Credits
|
||||
|
||||
* [stb_image](https://github.com/nothings/stb/blob/master/stb_image.h)
|
||||
* [stb_image_write](https://github.com/nothings/stb/blob/master/stb_image_write.h)
|
||||
Here I shall list all external libraries used by SoftLK:
|
||||
|
||||
* [SDL2](https://www.libsdl.org/)
|
||||
* [glad](https://glad.dav1d.de/)
|
||||
* [stb_image](https://github.com/nothings/stb/blob/master/stb_image.h)
|
||||
* [stb_image_write](https://github.com/nothings/stb/blob/master/stb_image_write.h)
|
||||
* [stb_rect_pack](https://github.com/nothings/stb/blob/master/stb_rect_pack.h)
|
||||
|
||||
## Gallery
|
||||
|
||||
|
|
2
src/glad/glad.c → external/glad.c
vendored
2
src/glad/glad.c → external/glad.c
vendored
|
@ -630,7 +630,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../include/glad/glad.h"
|
||||
#include "glad.h"
|
||||
|
||||
static void* get_proc(const char *namez);
|
||||
|
0
include/glad/glad.h → external/glad.h
vendored
0
include/glad/glad.h → external/glad.h
vendored
214
src/SLK/stb_image.h → external/stb_image.h
vendored
214
src/SLK/stb_image.h → external/stb_image.h
vendored
|
@ -1,4 +1,4 @@
|
|||
/* stb_image - v2.25 - public domain image loader - http://nothings.org/stb
|
||||
/* stb_image - v2.26 - public domain image loader - http://nothings.org/stb
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Do this:
|
||||
|
@ -48,6 +48,7 @@ LICENSE
|
|||
|
||||
RECENT REVISION HISTORY:
|
||||
|
||||
2.26 (2020-07-13) many minor fixes
|
||||
2.25 (2020-02-02) fix warnings
|
||||
2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
|
||||
2.23 (2019-08-11) fix clang static analysis warning
|
||||
|
@ -93,22 +94,30 @@ RECENT REVISION HISTORY:
|
|||
Carmelo J Fdez-Aguera
|
||||
|
||||
Bug & warning fixes
|
||||
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||
Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan
|
||||
Dave Moore Roy Eltham Hayaki Saito Nathan Reed
|
||||
Won Chun Luke Graham Johan Duparc Nick Verigakis
|
||||
the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh
|
||||
Janez Zemva John Bartholomew Michal Cichon github:romigrou
|
||||
Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
|
||||
Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar
|
||||
Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex
|
||||
Ryamond Barbiero Paul Du Bois Engin Manap github:grim210
|
||||
Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw
|
||||
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
|
||||
Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
|
||||
Christian Floisand Kevin Schmidt JR Smith github:darealshinji
|
||||
Brad Weinberger Matvey Cherevko github:Michaelangel007
|
||||
Blazej Dariusz Roszkowski Alexander Veselov
|
||||
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||
Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
|
||||
Phil Jordan Dave Moore Roy Eltham
|
||||
Hayaki Saito Nathan Reed Won Chun
|
||||
Luke Graham Johan Duparc Nick Verigakis the Horde3D community
|
||||
Thomas Ruf Ronny Chevalier github:rlyeh
|
||||
Janez Zemva John Bartholomew Michal Cichon github:romigrou
|
||||
Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
|
||||
Laurent Gomila Cort Stratton github:snagar
|
||||
Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex
|
||||
Cass Everitt Ryamond Barbiero github:grim210
|
||||
Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
|
||||
Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
|
||||
Josh Tobin Matthew Gregan github:poppolopoppo
|
||||
Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
|
||||
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
|
||||
Brad Weinberger Matvey Cherevko [reserved]
|
||||
Luca Sas Alexander Veselov Zack Middleton [reserved]
|
||||
Ryan C. Gordon [reserved] [reserved]
|
||||
DO NOT ADD YOUR NAME HERE
|
||||
|
||||
To add your name to the credits, pick a random blank space in the middle and fill it.
|
||||
80% of merge conflicts on stb PRs are due to people adding their name at the end
|
||||
of the credits.
|
||||
*/
|
||||
|
||||
#ifndef STBI_INCLUDE_STB_IMAGE_H
|
||||
|
@ -318,7 +327,14 @@ RECENT REVISION HISTORY:
|
|||
// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
|
||||
// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
|
||||
//
|
||||
|
||||
// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater
|
||||
// than that size (in either width or height) without further processing.
|
||||
// This is to let programs in the wild set an upper bound to prevent
|
||||
// denial-of-service attacks on untrusted data, as one could generate a
|
||||
// valid image of gigantic dimensions and force stb_image to allocate a
|
||||
// huge block of memory and spend disproportionate time decoding it. By
|
||||
// default this is set to (1 << 24), which is 16777216, but that's still
|
||||
// very big.
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
#include <stdio.h>
|
||||
|
@ -574,13 +590,19 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
|
|||
#ifndef STBI_NO_THREAD_LOCALS
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define STBI_THREAD_LOCAL thread_local
|
||||
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
#define STBI_THREAD_LOCAL _Thread_local
|
||||
#elif defined(__GNUC__)
|
||||
#elif defined(__GNUC__) && __GNUC__ < 5
|
||||
#define STBI_THREAD_LOCAL __thread
|
||||
#elif defined(_MSC_VER)
|
||||
#define STBI_THREAD_LOCAL __declspec(thread)
|
||||
#endif
|
||||
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
|
||||
#define STBI_THREAD_LOCAL _Thread_local
|
||||
#endif
|
||||
|
||||
#ifndef STBI_THREAD_LOCAL
|
||||
#if defined(__GNUC__)
|
||||
#define STBI_THREAD_LOCAL __thread
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -734,6 +756,10 @@ static int stbi__sse2_available(void)
|
|||
#define STBI_SIMD_ALIGN(type, name) type name
|
||||
#endif
|
||||
|
||||
#ifndef STBI_MAX_DIMENSIONS
|
||||
#define STBI_MAX_DIMENSIONS (1 << 24)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////
|
||||
//
|
||||
// stbi__context struct and start_xxx functions
|
||||
|
@ -751,6 +777,7 @@ typedef struct
|
|||
int read_from_callbacks;
|
||||
int buflen;
|
||||
stbi_uc buffer_start[128];
|
||||
int callback_already_read;
|
||||
|
||||
stbi_uc *img_buffer, *img_buffer_end;
|
||||
stbi_uc *img_buffer_original, *img_buffer_original_end;
|
||||
|
@ -764,6 +791,7 @@ static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
|
|||
{
|
||||
s->io.read = NULL;
|
||||
s->read_from_callbacks = 0;
|
||||
s->callback_already_read = 0;
|
||||
s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
|
||||
s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
|
||||
}
|
||||
|
@ -775,7 +803,8 @@ static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *
|
|||
s->io_user_data = user;
|
||||
s->buflen = sizeof(s->buffer_start);
|
||||
s->read_from_callbacks = 1;
|
||||
s->img_buffer_original = s->buffer_start;
|
||||
s->callback_already_read = 0;
|
||||
s->img_buffer = s->img_buffer_original = s->buffer_start;
|
||||
stbi__refill_buffer(s);
|
||||
s->img_buffer_original_end = s->img_buffer_end;
|
||||
}
|
||||
|
@ -789,12 +818,17 @@ static int stbi__stdio_read(void *user, char *data, int size)
|
|||
|
||||
static void stbi__stdio_skip(void *user, int n)
|
||||
{
|
||||
int ch;
|
||||
fseek((FILE*) user, n, SEEK_CUR);
|
||||
ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */
|
||||
if (ch != EOF) {
|
||||
ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */
|
||||
}
|
||||
}
|
||||
|
||||
static int stbi__stdio_eof(void *user)
|
||||
{
|
||||
return feof((FILE*) user);
|
||||
return feof((FILE*) user) || ferror((FILE *) user);
|
||||
}
|
||||
|
||||
static stbi_io_callbacks stbi__stdio_callbacks =
|
||||
|
@ -1171,8 +1205,10 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x,
|
|||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
|
||||
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
|
||||
|
||||
if (ri.bits_per_channel != 8) {
|
||||
STBI_ASSERT(ri.bits_per_channel == 16);
|
||||
result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
ri.bits_per_channel = 8;
|
||||
}
|
||||
|
@ -1195,8 +1231,10 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
|
|||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
// it is the responsibility of the loaders to make sure we get either 8 or 16 bit.
|
||||
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
|
||||
|
||||
if (ri.bits_per_channel != 16) {
|
||||
STBI_ASSERT(ri.bits_per_channel == 8);
|
||||
result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
ri.bits_per_channel = 16;
|
||||
}
|
||||
|
@ -1499,6 +1537,7 @@ enum
|
|||
static void stbi__refill_buffer(stbi__context *s)
|
||||
{
|
||||
int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);
|
||||
s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original);
|
||||
if (n == 0) {
|
||||
// at end of file, treat same as if from memory, but need to handle case
|
||||
// where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file
|
||||
|
@ -1544,6 +1583,7 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
|
|||
#else
|
||||
static void stbi__skip(stbi__context *s, int n)
|
||||
{
|
||||
if (n == 0) return; // already there!
|
||||
if (n < 0) {
|
||||
s->img_buffer = s->img_buffer_end;
|
||||
return;
|
||||
|
@ -1686,7 +1726,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
|||
STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
|
||||
STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;
|
||||
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
|
||||
default: STBI_ASSERT(0);
|
||||
default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion");
|
||||
}
|
||||
#undef STBI__CASE
|
||||
}
|
||||
|
@ -1743,7 +1783,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
|
|||
STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
|
||||
STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;
|
||||
STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;
|
||||
default: STBI_ASSERT(0);
|
||||
default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion");
|
||||
}
|
||||
#undef STBI__CASE
|
||||
}
|
||||
|
@ -2052,7 +2092,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 < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
|
||||
if (n < 0 || n >= (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))) return 0;
|
||||
j->code_buffer = k & ~stbi__bmask[n];
|
||||
k &= stbi__bmask[n];
|
||||
j->code_bits -= n;
|
||||
|
@ -2163,6 +2203,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
|
|||
// first scan for DC coefficient, must be first
|
||||
memset(data,0,64*sizeof(data[0])); // 0 all the ac values now
|
||||
t = stbi__jpeg_huff_decode(j, hdc);
|
||||
if (t == -1) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
diff = t ? stbi__extend_receive(j, t) : 0;
|
||||
|
||||
dc = j->img_comp[b].dc_pred + diff;
|
||||
|
@ -3153,6 +3194,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
|||
p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
|
||||
s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
|
||||
s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
c = stbi__get8(s);
|
||||
if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");
|
||||
s->img_n = c;
|
||||
|
@ -4033,16 +4076,23 @@ typedef struct
|
|||
stbi__zhuffman z_length, z_distance;
|
||||
} stbi__zbuf;
|
||||
|
||||
stbi_inline static int stbi__zeof(stbi__zbuf *z)
|
||||
{
|
||||
return (z->zbuffer >= z->zbuffer_end);
|
||||
}
|
||||
|
||||
stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)
|
||||
{
|
||||
if (z->zbuffer >= z->zbuffer_end) return 0;
|
||||
return *z->zbuffer++;
|
||||
return stbi__zeof(z) ? 0 : *z->zbuffer++;
|
||||
}
|
||||
|
||||
static void stbi__fill_bits(stbi__zbuf *z)
|
||||
{
|
||||
do {
|
||||
STBI_ASSERT(z->code_buffer < (1U << z->num_bits));
|
||||
if (z->code_buffer >= (1U << z->num_bits)) {
|
||||
z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */
|
||||
return;
|
||||
}
|
||||
z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;
|
||||
z->num_bits += 8;
|
||||
} while (z->num_bits <= 24);
|
||||
|
@ -4067,10 +4117,11 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
|
|||
for (s=STBI__ZFAST_BITS+1; ; ++s)
|
||||
if (k < z->maxcode[s])
|
||||
break;
|
||||
if (s == 16) return -1; // invalid code!
|
||||
if (s >= 16) return -1; // invalid code!
|
||||
// code size is s, so:
|
||||
b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
|
||||
STBI_ASSERT(z->size[b] == s);
|
||||
if (b >= sizeof (z->size)) return -1; // some data was corrupt somewhere!
|
||||
if (z->size[b] != s) return -1; // was originally an assert, but report failure instead.
|
||||
a->code_buffer >>= s;
|
||||
a->num_bits -= s;
|
||||
return z->value[b];
|
||||
|
@ -4079,7 +4130,12 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)
|
|||
stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
|
||||
{
|
||||
int b,s;
|
||||
if (a->num_bits < 16) stbi__fill_bits(a);
|
||||
if (a->num_bits < 16) {
|
||||
if (stbi__zeof(a)) {
|
||||
return -1; /* report error for unexpected end of data. */
|
||||
}
|
||||
stbi__fill_bits(a);
|
||||
}
|
||||
b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
|
||||
if (b) {
|
||||
s = b >> 9;
|
||||
|
@ -4093,13 +4149,16 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
|
|||
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
|
||||
{
|
||||
char *q;
|
||||
int cur, limit, old_limit;
|
||||
unsigned int cur, limit, old_limit;
|
||||
z->zout = zout;
|
||||
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
|
||||
cur = (int) (z->zout - z->zout_start);
|
||||
limit = old_limit = (int) (z->zout_end - z->zout_start);
|
||||
while (cur + n > limit)
|
||||
cur = (unsigned int) (z->zout - z->zout_start);
|
||||
limit = old_limit = (unsigned) (z->zout_end - z->zout_start);
|
||||
if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory");
|
||||
while (cur + n > limit) {
|
||||
if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory");
|
||||
limit *= 2;
|
||||
}
|
||||
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
|
||||
STBI_NOTUSED(old_limit);
|
||||
if (q == NULL) return stbi__err("outofmem", "Out of memory");
|
||||
|
@ -4197,11 +4256,12 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
|
|||
c = stbi__zreceive(a,2)+3;
|
||||
if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");
|
||||
fill = lencodes[n-1];
|
||||
} else if (c == 17)
|
||||
} else if (c == 17) {
|
||||
c = stbi__zreceive(a,3)+3;
|
||||
else {
|
||||
STBI_ASSERT(c == 18);
|
||||
} else if (c == 18) {
|
||||
c = stbi__zreceive(a,7)+11;
|
||||
} else {
|
||||
return stbi__err("bad codelengths", "Corrupt PNG");
|
||||
}
|
||||
if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");
|
||||
memset(lencodes+n, fill, c);
|
||||
|
@ -4227,7 +4287,7 @@ static int stbi__parse_uncompressed_block(stbi__zbuf *a)
|
|||
a->code_buffer >>= 8;
|
||||
a->num_bits -= 8;
|
||||
}
|
||||
STBI_ASSERT(a->num_bits == 0);
|
||||
if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG");
|
||||
// now fill header the normal way
|
||||
while (k < 4)
|
||||
header[k++] = stbi__zget8(a);
|
||||
|
@ -4249,6 +4309,7 @@ static int stbi__parse_zlib_header(stbi__zbuf *a)
|
|||
int cm = cmf & 15;
|
||||
/* int cinfo = cmf >> 4; */
|
||||
int flg = stbi__zget8(a);
|
||||
if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
|
||||
if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec
|
||||
if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
|
||||
if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png
|
||||
|
@ -4510,7 +4571,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|||
return stbi__err("invalid filter","Corrupt PNG");
|
||||
|
||||
if (depth < 8) {
|
||||
STBI_ASSERT(img_width_bytes <= x);
|
||||
if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
|
||||
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
|
||||
filter_bytes = 1;
|
||||
width = img_width_bytes;
|
||||
|
@ -4905,8 +4966,10 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|||
if (!first) return stbi__err("multiple IHDR","Corrupt PNG");
|
||||
first = 0;
|
||||
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
|
||||
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
||||
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
||||
s->img_x = stbi__get32be(s);
|
||||
s->img_y = stbi__get32be(s);
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
|
||||
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
|
||||
if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
|
||||
|
@ -5055,10 +5118,12 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st
|
|||
void *result=NULL;
|
||||
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
|
||||
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
|
||||
if (p->depth < 8)
|
||||
if (p->depth <= 8)
|
||||
ri->bits_per_channel = 8;
|
||||
else if (p->depth == 16)
|
||||
ri->bits_per_channel = 16;
|
||||
else
|
||||
ri->bits_per_channel = p->depth;
|
||||
return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth");
|
||||
result = p->out;
|
||||
p->out = NULL;
|
||||
if (req_comp && req_comp != p->s->img_out_n) {
|
||||
|
@ -5219,6 +5284,8 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
|
|||
info->mr = info->mg = info->mb = info->ma = 0;
|
||||
info->extra_read = 14;
|
||||
|
||||
if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP");
|
||||
|
||||
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
|
||||
if (hsz == 12) {
|
||||
s->img_x = stbi__get16le(s);
|
||||
|
@ -5310,6 +5377,9 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
flip_vertically = ((int) s->img_y) > 0;
|
||||
s->img_y = abs((int) s->img_y);
|
||||
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
mr = info.mr;
|
||||
mg = info.mg;
|
||||
mb = info.mb;
|
||||
|
@ -5324,7 +5394,10 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
psize = (info.offset - info.extra_read - info.hsz) >> 2;
|
||||
}
|
||||
if (psize == 0) {
|
||||
STBI_ASSERT(info.offset == (s->img_buffer - s->buffer_start));
|
||||
STBI_ASSERT(info.offset == s->callback_already_read + (int) (s->img_buffer - s->img_buffer_original));
|
||||
if (info.offset != s->callback_already_read + (s->img_buffer - s->buffer_start)) {
|
||||
return stbi__errpuc("bad offset", "Corrupt BMP");
|
||||
}
|
||||
}
|
||||
|
||||
if (info.bpp == 24 && ma == 0xff000000)
|
||||
|
@ -5419,6 +5492,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);
|
||||
bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);
|
||||
ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);
|
||||
if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }
|
||||
}
|
||||
for (j=0; j < (int) s->img_y; ++j) {
|
||||
if (easy) {
|
||||
|
@ -5643,6 +5717,9 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
STBI_NOTUSED(tga_x_origin); // @TODO
|
||||
STBI_NOTUSED(tga_y_origin); // @TODO
|
||||
|
||||
if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
// do a tiny bit of precessing
|
||||
if ( tga_image_type >= 8 )
|
||||
{
|
||||
|
@ -5682,6 +5759,11 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
// do I need to load a palette?
|
||||
if ( tga_indexed)
|
||||
{
|
||||
if (tga_palette_len == 0) { /* you have to have at least one entry! */
|
||||
STBI_FREE(tga_data);
|
||||
return stbi__errpuc("bad palette", "Corrupt TGA");
|
||||
}
|
||||
|
||||
// any data to skip? (offset usually = 0)
|
||||
stbi__skip(s, tga_palette_start );
|
||||
// load the palette
|
||||
|
@ -5890,6 +5972,9 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
h = stbi__get32be(s);
|
||||
w = stbi__get32be(s);
|
||||
|
||||
if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
// Make sure the depth is 8 bits.
|
||||
bitdepth = stbi__get16be(s);
|
||||
if (bitdepth != 8 && bitdepth != 16)
|
||||
|
@ -6244,6 +6329,10 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c
|
|||
|
||||
x = stbi__get16be(s);
|
||||
y = stbi__get16be(s);
|
||||
|
||||
if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");
|
||||
if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");
|
||||
|
||||
|
@ -6352,6 +6441,9 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
|
|||
g->ratio = stbi__get8(s);
|
||||
g->transparent = -1;
|
||||
|
||||
if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");
|
||||
|
||||
if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments
|
||||
|
||||
if (is_info) return 1;
|
||||
|
@ -6529,7 +6621,7 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
|
|||
memset(g->history, 0x00, pcount); // pixels that were affected previous frame
|
||||
first_frame = 1;
|
||||
} else {
|
||||
// second frame - how do we dispoase of the previous one?
|
||||
// second frame - how do we dispose of the previous one?
|
||||
dispose = (g->eflags & 0x1C) >> 2;
|
||||
pcount = g->w * g->h;
|
||||
|
||||
|
@ -6683,6 +6775,8 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
stbi_uc *two_back = 0;
|
||||
stbi__gif g;
|
||||
int stride;
|
||||
int out_size = 0;
|
||||
int delays_size = 0;
|
||||
memset(&g, 0, sizeof(g));
|
||||
if (delays) {
|
||||
*delays = 0;
|
||||
|
@ -6699,22 +6793,28 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
stride = g.w * g.h * 4;
|
||||
|
||||
if (out) {
|
||||
void *tmp = (stbi_uc*) STBI_REALLOC( out, layers * stride );
|
||||
void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
|
||||
if (NULL == tmp) {
|
||||
STBI_FREE(g.out);
|
||||
STBI_FREE(g.history);
|
||||
STBI_FREE(g.background);
|
||||
return stbi__errpuc("outofmem", "Out of memory");
|
||||
}
|
||||
else
|
||||
out = (stbi_uc*) tmp;
|
||||
else {
|
||||
out = (stbi_uc*) tmp;
|
||||
out_size = layers * stride;
|
||||
}
|
||||
|
||||
if (delays) {
|
||||
*delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers );
|
||||
*delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
|
||||
delays_size = layers * sizeof(int);
|
||||
}
|
||||
} else {
|
||||
out = (stbi_uc*)stbi__malloc( layers * stride );
|
||||
out_size = layers * stride;
|
||||
if (delays) {
|
||||
*delays = (int*) stbi__malloc( layers * sizeof(int) );
|
||||
delays_size = layers * sizeof(int);
|
||||
}
|
||||
}
|
||||
memcpy( out + ((layers - 1) * stride), u, stride );
|
||||
|
@ -6893,6 +6993,9 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
|||
token += 3;
|
||||
width = (int) strtol(token, NULL, 10);
|
||||
|
||||
if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
|
||||
if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");
|
||||
|
||||
*x = width;
|
||||
*y = height;
|
||||
|
||||
|
@ -7207,6 +7310,9 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
|
||||
return 0;
|
||||
|
||||
if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");
|
||||
|
||||
*x = s->img_x;
|
||||
*y = s->img_y;
|
||||
if (comp) *comp = s->img_n;
|
|
@ -1,4 +1,4 @@
|
|||
/* stb_image_write - v1.14 - public domain - http://nothings.org/stb
|
||||
/* stb_image_write - v1.15 - public domain - http://nothings.org/stb
|
||||
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
|
@ -267,6 +267,8 @@ typedef struct
|
|||
{
|
||||
stbi_write_func *func;
|
||||
void *context;
|
||||
unsigned char buffer[64];
|
||||
int buf_used;
|
||||
} stbi__write_context;
|
||||
|
||||
// initialize a callback-based context
|
||||
|
@ -380,16 +382,36 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
|
|||
va_end(v);
|
||||
}
|
||||
|
||||
static void stbiw__write_flush(stbi__write_context *s)
|
||||
{
|
||||
if (s->buf_used) {
|
||||
s->func(s->context, &s->buffer, s->buf_used);
|
||||
s->buf_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void stbiw__putc(stbi__write_context *s, unsigned char c)
|
||||
{
|
||||
s->func(s->context, &c, 1);
|
||||
}
|
||||
|
||||
static void stbiw__write1(stbi__write_context *s, unsigned char a)
|
||||
{
|
||||
if (s->buf_used + 1 > sizeof(s->buffer))
|
||||
stbiw__write_flush(s);
|
||||
s->buffer[s->buf_used++] = a;
|
||||
}
|
||||
|
||||
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
|
||||
{
|
||||
unsigned char arr[3];
|
||||
arr[0] = a; arr[1] = b; arr[2] = c;
|
||||
s->func(s->context, arr, 3);
|
||||
int n;
|
||||
if (s->buf_used + 3 > sizeof(s->buffer))
|
||||
stbiw__write_flush(s);
|
||||
n = s->buf_used;
|
||||
s->buf_used = n+3;
|
||||
s->buffer[n+0] = a;
|
||||
s->buffer[n+1] = b;
|
||||
s->buffer[n+2] = c;
|
||||
}
|
||||
|
||||
static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
|
||||
|
@ -398,7 +420,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
int k;
|
||||
|
||||
if (write_alpha < 0)
|
||||
s->func(s->context, &d[comp - 1], 1);
|
||||
stbiw__write1(s, d[comp - 1]);
|
||||
|
||||
switch (comp) {
|
||||
case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
|
||||
|
@ -406,7 +428,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
if (expand_mono)
|
||||
stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
|
||||
else
|
||||
s->func(s->context, d, 1); // monochrome TGA
|
||||
stbiw__write1(s, d[0]); // monochrome TGA
|
||||
break;
|
||||
case 4:
|
||||
if (!write_alpha) {
|
||||
|
@ -422,7 +444,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in
|
|||
break;
|
||||
}
|
||||
if (write_alpha > 0)
|
||||
s->func(s->context, &d[comp - 1], 1);
|
||||
stbiw__write1(s, d[comp - 1]);
|
||||
}
|
||||
|
||||
static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
|
||||
|
@ -447,6 +469,7 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i
|
|||
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
|
||||
stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
|
||||
}
|
||||
stbiw__write_flush(s);
|
||||
s->func(s->context, &zero, scanline_pad);
|
||||
}
|
||||
}
|
||||
|
@ -476,7 +499,7 @@ static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, c
|
|||
|
||||
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_bmp_core(&s, x, y, comp, data);
|
||||
}
|
||||
|
@ -484,7 +507,7 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_bmp_core(&s, x, y, comp, data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -557,24 +580,25 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v
|
|||
|
||||
if (diff) {
|
||||
unsigned char header = STBIW_UCHAR(len - 1);
|
||||
s->func(s->context, &header, 1);
|
||||
stbiw__write1(s, header);
|
||||
for (k = 0; k < len; ++k) {
|
||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
|
||||
}
|
||||
} else {
|
||||
unsigned char header = STBIW_UCHAR(len - 129);
|
||||
s->func(s->context, &header, 1);
|
||||
stbiw__write1(s, header);
|
||||
stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
stbiw__write_flush(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
||||
}
|
||||
|
@ -582,7 +606,7 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -748,7 +772,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
|
|||
|
||||
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||
}
|
||||
|
@ -756,7 +780,7 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
|
||||
stbi__end_write_file(&s);
|
||||
|
@ -1552,7 +1576,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
|
|||
|
||||
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
stbi__start_write_callbacks(&s, func, context);
|
||||
return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
|
||||
}
|
||||
|
@ -1561,7 +1585,7 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x,
|
|||
#ifndef STBI_WRITE_NO_STDIO
|
||||
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
|
||||
{
|
||||
stbi__write_context s;
|
||||
stbi__write_context s = { 0 };
|
||||
if (stbi__start_write_file(&s,filename)) {
|
||||
int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
|
||||
stbi__end_write_file(&s);
|
628
external/stb_rect_pack.h
vendored
Normal file
628
external/stb_rect_pack.h
vendored
Normal file
|
@ -0,0 +1,628 @@
|
|||
// stb_rect_pack.h - v1.00 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Not necessarily the awesomest packing method, but better than
|
||||
// the totally naive one in stb_truetype (which is primarily what
|
||||
// this is meant to replace).
|
||||
//
|
||||
// Has only had a few tests run, may have issues.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Please note: better rectangle packers are welcome! Please
|
||||
// implement them to the same API, but with a different init
|
||||
// function.
|
||||
//
|
||||
// Credits
|
||||
//
|
||||
// Library
|
||||
// Sean Barrett
|
||||
// Minor features
|
||||
// Martins Mozeiko
|
||||
// github:IntellectualKitty
|
||||
//
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
// Fabian Giesen
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
// 0.09 (2016-08-27) fix compiler warnings
|
||||
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||
// 0.01: initial release
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// See end of file for license information.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// INCLUDE SECTION
|
||||
//
|
||||
|
||||
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||
|
||||
#define STB_RECT_PACK_VERSION 1
|
||||
|
||||
#ifdef STBRP_STATIC
|
||||
#define STBRP_DEF static
|
||||
#else
|
||||
#define STBRP_DEF extern
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct stbrp_context stbrp_context;
|
||||
typedef struct stbrp_node stbrp_node;
|
||||
typedef struct stbrp_rect stbrp_rect;
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
typedef int stbrp_coord;
|
||||
#else
|
||||
typedef unsigned short stbrp_coord;
|
||||
#endif
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||
// are 'num_rects' many of them.
|
||||
//
|
||||
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||
// have the 'was_packed' flag set to 0.
|
||||
//
|
||||
// You should not try to access the 'rects' array from another thread
|
||||
// while this function is running, as the function temporarily reorders
|
||||
// the array while it executes.
|
||||
//
|
||||
// To pack into another rectangle, you need to call stbrp_init_target
|
||||
// again. To continue packing into the same rectangle, you can call
|
||||
// this function again. Calling this multiple times with multiple rect
|
||||
// arrays will probably produce worse packing results than calling it
|
||||
// a single time with the full rectangle array, but the option is
|
||||
// available.
|
||||
//
|
||||
// The function returns 1 if all of the rectangles were successfully
|
||||
// packed and 0 otherwise.
|
||||
|
||||
struct stbrp_rect
|
||||
{
|
||||
// reserved for your use:
|
||||
int id;
|
||||
|
||||
// input:
|
||||
stbrp_coord w, h;
|
||||
|
||||
// output:
|
||||
stbrp_coord x, y;
|
||||
int was_packed; // non-zero if valid packing
|
||||
|
||||
}; // 16 bytes, nominally
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||
// Initialize a rectangle packer to:
|
||||
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||
//
|
||||
// You must call this function every time you start packing into a new target.
|
||||
//
|
||||
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||
// the call (or calls) finish.
|
||||
//
|
||||
// Note: to guarantee best results, either:
|
||||
// 1. make sure 'num_nodes' >= 'width'
|
||||
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||
//
|
||||
// If you don't do either of the above things, widths will be quantized to multiples
|
||||
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||
//
|
||||
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||
// may run out of temporary storage and be unable to pack some rectangles.
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||
// Optionally call this function after init but before doing any packing to
|
||||
// change the handling of the out-of-temp-memory scenario, described above.
|
||||
// If you call init again, this will be reset to the default (false).
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||
// Optionally select which packing heuristic the library should use. Different
|
||||
// heuristics will produce better/worse results for different data sets.
|
||||
// If you call init again, this will be reset to the default.
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP_HEURISTIC_Skyline_default=0,
|
||||
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// the details of the following structures don't matter to you, but they must
|
||||
// be visible so you can handle the memory allocations for them
|
||||
|
||||
struct stbrp_node
|
||||
{
|
||||
stbrp_coord x,y;
|
||||
stbrp_node *next;
|
||||
};
|
||||
|
||||
struct stbrp_context
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int align;
|
||||
int init_mode;
|
||||
int heuristic;
|
||||
int num_nodes;
|
||||
stbrp_node *active_head;
|
||||
stbrp_node *free_head;
|
||||
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPLEMENTATION SECTION
|
||||
//
|
||||
|
||||
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||
#ifndef STBRP_SORT
|
||||
#include <stdlib.h>
|
||||
#define STBRP_SORT qsort
|
||||
#endif
|
||||
|
||||
#ifndef STBRP_ASSERT
|
||||
#include <assert.h>
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP__INIT_skyline = 1
|
||||
};
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||
{
|
||||
switch (context->init_mode) {
|
||||
case STBRP__INIT_skyline:
|
||||
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||
context->heuristic = heuristic;
|
||||
break;
|
||||
default:
|
||||
STBRP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||
{
|
||||
if (allow_out_of_mem)
|
||||
// if it's ok to run out of memory, then don't bother aligning them;
|
||||
// this gives better packing, but may fail due to OOM (even though
|
||||
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||
context->align = 1;
|
||||
else {
|
||||
// if it's not ok to run out of memory, then quantize the widths
|
||||
// so that num_nodes is always enough nodes.
|
||||
//
|
||||
// I.e. num_nodes * align >= width
|
||||
// align >= width / num_nodes
|
||||
// align = ceil(width/num_nodes)
|
||||
|
||||
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||
{
|
||||
int i;
|
||||
#ifndef STBRP_LARGE_RECTS
|
||||
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
|
||||
#endif
|
||||
|
||||
for (i=0; i < num_nodes-1; ++i)
|
||||
nodes[i].next = &nodes[i+1];
|
||||
nodes[i].next = NULL;
|
||||
context->init_mode = STBRP__INIT_skyline;
|
||||
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||
context->free_head = &nodes[0];
|
||||
context->active_head = &context->extra[0];
|
||||
context->width = width;
|
||||
context->height = height;
|
||||
context->num_nodes = num_nodes;
|
||||
stbrp_setup_allow_out_of_mem(context, 0);
|
||||
|
||||
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||
context->extra[0].x = 0;
|
||||
context->extra[0].y = 0;
|
||||
context->extra[0].next = &context->extra[1];
|
||||
context->extra[1].x = (stbrp_coord) width;
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
context->extra[1].y = (1<<30);
|
||||
#else
|
||||
context->extra[1].y = 65535;
|
||||
#endif
|
||||
context->extra[1].next = NULL;
|
||||
}
|
||||
|
||||
// find minimum y position if it starts at x1
|
||||
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||
{
|
||||
stbrp_node *node = first;
|
||||
int x1 = x0 + width;
|
||||
int min_y, visited_width, waste_area;
|
||||
|
||||
STBRP__NOTUSED(c);
|
||||
|
||||
STBRP_ASSERT(first->x <= x0);
|
||||
|
||||
#if 0
|
||||
// skip in case we're past the node
|
||||
while (node->next->x <= x0)
|
||||
++node;
|
||||
#else
|
||||
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||
#endif
|
||||
|
||||
STBRP_ASSERT(node->x <= x0);
|
||||
|
||||
min_y = 0;
|
||||
waste_area = 0;
|
||||
visited_width = 0;
|
||||
while (node->x < x1) {
|
||||
if (node->y > min_y) {
|
||||
// raise min_y higher.
|
||||
// we've accounted for all waste up to min_y,
|
||||
// but we'll now add more waste for everything we've visted
|
||||
waste_area += visited_width * (node->y - min_y);
|
||||
min_y = node->y;
|
||||
// the first time through, visited_width might be reduced
|
||||
if (node->x < x0)
|
||||
visited_width += node->next->x - x0;
|
||||
else
|
||||
visited_width += node->next->x - node->x;
|
||||
} else {
|
||||
// add waste area
|
||||
int under_width = node->next->x - node->x;
|
||||
if (under_width + visited_width > width)
|
||||
under_width = width - visited_width;
|
||||
waste_area += under_width * (min_y - node->y);
|
||||
visited_width += under_width;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
*pwaste = waste_area;
|
||||
return min_y;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x,y;
|
||||
stbrp_node **prev_link;
|
||||
} stbrp__findresult;
|
||||
|
||||
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||
{
|
||||
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||
stbrp__findresult fr;
|
||||
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||
|
||||
// align to multiple of c->align
|
||||
width = (width + c->align - 1);
|
||||
width -= width % c->align;
|
||||
STBRP_ASSERT(width % c->align == 0);
|
||||
|
||||
// if it can't possibly fit, bail immediately
|
||||
if (width > c->width || height > c->height) {
|
||||
fr.prev_link = NULL;
|
||||
fr.x = fr.y = 0;
|
||||
return fr;
|
||||
}
|
||||
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
while (node->x + width <= c->width) {
|
||||
int y,waste;
|
||||
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||
// bottom left
|
||||
if (y < best_y) {
|
||||
best_y = y;
|
||||
best = prev;
|
||||
}
|
||||
} else {
|
||||
// best-fit
|
||||
if (y + height <= c->height) {
|
||||
// can only use it if it first vertically
|
||||
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||
|
||||
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||
//
|
||||
// e.g, if fitting
|
||||
//
|
||||
// ____________________
|
||||
// |____________________|
|
||||
//
|
||||
// into
|
||||
//
|
||||
// | |
|
||||
// | ____________|
|
||||
// |____________|
|
||||
//
|
||||
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||
//
|
||||
// This makes BF take about 2x the time
|
||||
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||
tail = c->active_head;
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
// find first node that's admissible
|
||||
while (tail->x < width)
|
||||
tail = tail->next;
|
||||
while (tail) {
|
||||
int xpos = tail->x - width;
|
||||
int y,waste;
|
||||
STBRP_ASSERT(xpos >= 0);
|
||||
// find the left position that matches this
|
||||
while (node->next->x <= xpos) {
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||
if (y + height <= c->height) {
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
STBRP_ASSERT(y <= best_y);
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
tail = tail->next;
|
||||
}
|
||||
}
|
||||
|
||||
fr.prev_link = best;
|
||||
fr.x = best_x;
|
||||
fr.y = best_y;
|
||||
return fr;
|
||||
}
|
||||
|
||||
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||
{
|
||||
// find best position according to heuristic
|
||||
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||
stbrp_node *node, *cur;
|
||||
|
||||
// bail if:
|
||||
// 1. it failed
|
||||
// 2. the best node doesn't fit (we don't always check this)
|
||||
// 3. we're out of memory
|
||||
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||
res.prev_link = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
// on success, create new node
|
||||
node = context->free_head;
|
||||
node->x = (stbrp_coord) res.x;
|
||||
node->y = (stbrp_coord) (res.y + height);
|
||||
|
||||
context->free_head = node->next;
|
||||
|
||||
// insert the new node into the right starting point, and
|
||||
// let 'cur' point to the remaining nodes needing to be
|
||||
// stiched back in
|
||||
|
||||
cur = *res.prev_link;
|
||||
if (cur->x < res.x) {
|
||||
// preserve the existing one, so start testing with the next one
|
||||
stbrp_node *next = cur->next;
|
||||
cur->next = node;
|
||||
cur = next;
|
||||
} else {
|
||||
*res.prev_link = node;
|
||||
}
|
||||
|
||||
// from here, traverse cur and free the nodes, until we get to one
|
||||
// that shouldn't be freed
|
||||
while (cur->next && cur->next->x <= res.x + width) {
|
||||
stbrp_node *next = cur->next;
|
||||
// move the current node to the free list
|
||||
cur->next = context->free_head;
|
||||
context->free_head = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
// stitch the list back in
|
||||
node->next = cur;
|
||||
|
||||
if (cur->x < res.x + width)
|
||||
cur->x = (stbrp_coord) (res.x + width);
|
||||
|
||||
#ifdef _DEBUG
|
||||
cur = context->active_head;
|
||||
while (cur->x < context->width) {
|
||||
STBRP_ASSERT(cur->x < cur->next->x);
|
||||
cur = cur->next;
|
||||
}
|
||||
STBRP_ASSERT(cur->next == NULL);
|
||||
|
||||
{
|
||||
int count=0;
|
||||
cur = context->active_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
cur = context->free_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
STBRP_ASSERT(count == context->num_nodes+2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->h > q->h)
|
||||
return -1;
|
||||
if (p->h < q->h)
|
||||
return 1;
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
static int rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
#define STBRP__MAXVAL 0xffffffff
|
||||
#else
|
||||
#define STBRP__MAXVAL 0xffff
|
||||
#endif
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i, all_rects_packed = 1;
|
||||
|
||||
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = i;
|
||||
}
|
||||
|
||||
// sort according to heuristic
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||
} else {
|
||||
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||
if (fr.prev_link) {
|
||||
rects[i].x = (stbrp_coord) fr.x;
|
||||
rects[i].y = (stbrp_coord) fr.y;
|
||||
} else {
|
||||
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unsort
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||
|
||||
// set was_packed flags and all_rects_packed status
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||
if (!rects[i].was_packed)
|
||||
all_rects_packed = 0;
|
||||
}
|
||||
|
||||
// return the all_rects_packed status
|
||||
return all_rects_packed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
|
@ -17,8 +17,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
|
||||
#define _SLK_H_
|
||||
|
||||
#define SLK_log 0
|
||||
|
||||
//Includes
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -27,18 +25,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include "../glad/glad.h"
|
||||
|
||||
//Macros
|
||||
//Fast integer inbounds checking
|
||||
#define INBOUNDS(LOWER,UPPER,NUMBER) \
|
||||
((NUMBER-LOWER)<(UPPER-LOWER))
|
||||
|
||||
#define SIGNUM(NUM) \
|
||||
NUM==0?0:(NUM<0?-1:1)
|
||||
//Two integer swapping
|
||||
#define SWAP(x,y) \
|
||||
{ (x)=(x)^(y); (y)=(x)^(y); (x)=(x)^(y); }
|
||||
#include "../../external/glad.h"
|
||||
|
||||
//Internal includes
|
||||
#include "SLK_types.h"
|
||||
|
|
|
@ -18,7 +18,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
#define _SLK_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../glad/glad.h"
|
||||
#include "../../external/glad.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -74,11 +74,6 @@ typedef struct
|
|||
SLK_Pal_sprite **sheet;
|
||||
}SLK_Pal_sheet;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
}SLK_RGB_animation;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SLK_Pal_sprite *target;
|
||||
|
@ -144,7 +139,7 @@ enum SLK_mouse_button
|
|||
|
||||
enum SLK_layer
|
||||
{
|
||||
SLK_LAYER_PAL,SLK_LAYER_RGB,SLK_LAYER_GPU,
|
||||
SLK_LAYER_PAL,SLK_LAYER_RGB,
|
||||
};
|
||||
|
||||
enum SLK_mask
|
||||
|
|
28
lib/makefile
28
lib/makefile
|
@ -5,46 +5,46 @@ CFLAGS+=-lm -lSDL2 -lGL -Wall
|
|||
libSLK.a: glad.o SLK_core.o SLK_color.o SLK_draw_pal.o SLK_draw_rgb.o SLK_input.o SLK_layer.o SLK_palette.o SLK_render.o SLK_sprite_pal.o SLK_sprite_rgb.o SLK_timer.o SLK_sheet_rgb.o SLK_sheet_pal.o
|
||||
ar cr libSLK.a $^
|
||||
|
||||
glad.o: ../src/glad/glad.c ../include/glad/glad.h
|
||||
glad.o: ../external/glad.c ../external/glad.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_core.o: ../src/SLK/SLK_core.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h ../src/SLK/SLK_input_i.h ../src/SLK/SLK_render_i.h ../src/SLK/SLK_draw_rgb_i.h ../src/SLK/SLK_draw_pal_i.h ../src/SLK/SLK_layer_i.h
|
||||
SLK_core.o: ../src/SLK_core.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h ../src/SLK_input_i.h ../src/SLK_render_i.h ../src/SLK_draw_rgb_i.h ../src/SLK_draw_pal_i.h ../src/SLK_layer_i.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_color.o: ../src/SLK/SLK_color.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h
|
||||
SLK_color.o: ../src/SLK_color.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_draw_pal.o: ../src/SLK/SLK_draw_pal.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h ../src/SLK/SLK_draw_pal_i.h
|
||||
SLK_draw_pal.o: ../src/SLK_draw_pal.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h ../src/SLK_draw_pal_i.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_draw_rgb.o: ../src/SLK/SLK_draw_rgb.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h ../src/SLK/SLK_draw_rgb_i.h
|
||||
SLK_draw_rgb.o: ../src/SLK_draw_rgb.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h ../src/SLK_draw_rgb_i.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_input.o: ../src/SLK/SLK_input.c ../include/SLK/SLK_types.h ../src/SLK/SLK_input_i.h ../src/SLK/SLK_render_i.h ../src/SLK/SLK_layer_i.h
|
||||
SLK_input.o: ../src/SLK_input.c ../include/SLK/SLK_types.h ../src/SLK_input_i.h ../src/SLK_render_i.h ../src/SLK_layer_i.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_layer.o: ../src/SLK/SLK_layer.c ../include/glad/glad.h ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h ../src/SLK/SLK_render_i.h ../src/SLK/SLK_draw_rgb_i.h ../src/SLK/SLK_draw_pal_i.h ../src/SLK/SLK_layer_i.h
|
||||
SLK_layer.o: ../src/SLK_layer.c ../external/glad.h ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h ../src/SLK_render_i.h ../src/SLK_draw_rgb_i.h ../src/SLK_draw_pal_i.h ../src/SLK_layer_i.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_palette.o: ../src/SLK/SLK_palette.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h
|
||||
SLK_palette.o: ../src/SLK_palette.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_render.o: ../src/SLK/SLK_render.c ../include/glad/glad.h ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h ../src/SLK/SLK_render_i.h ../src/SLK/SLK_layer_i.h
|
||||
SLK_render.o: ../src/SLK_render.c ../external/glad.h ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h ../src/SLK_render_i.h ../src/SLK_layer_i.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_sprite_pal.o: ../src/SLK/SLK_sprite_pal.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h
|
||||
SLK_sprite_pal.o: ../src/SLK_sprite_pal.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_sprite_rgb.o: ../src/SLK/SLK_sprite_rgb.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h
|
||||
SLK_sprite_rgb.o: ../src/SLK_sprite_rgb.c ../include/SLK/SLK_types.h ../include/SLK/SLK_functions.h ../external/stb_image.h ../external/stb_image_write.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_timer.o: ../src/SLK/SLK_timer.c ../include/SLK/SLK_functions.h
|
||||
SLK_timer.o: ../src/SLK_timer.c ../include/SLK/SLK_functions.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_sheet_rgb.o: ../src/SLK/SLK_sheet_rgb.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h
|
||||
SLK_sheet_rgb.o: ../src/SLK_sheet_rgb.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
SLK_sheet_pal.o: ../src/SLK/SLK_sheet_pal.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h
|
||||
SLK_sheet_pal.o: ../src/SLK_sheet_pal.c ../include/SLK/SLK_functions.h ../include/SLK/SLK_types.h
|
||||
$(CC) -O3 -c $< $(CFLAGS)
|
||||
|
||||
clean:
|
||||
|
|
|
@ -17,8 +17,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
//-------------------------------------
|
||||
|
||||
//#defines
|
|
@ -20,8 +20,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
#include "SLK_input_i.h"
|
||||
#include "SLK_render_i.h"
|
||||
#include "SLK_draw_rgb_i.h"
|
|
@ -18,8 +18,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
#include "SLK_draw_pal_i.h"
|
||||
//-------------------------------------
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#define _SLK_DRAW_PAL_I_H_
|
||||
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
|
||||
SLK_Pal_sprite *target_pal;
|
||||
SLK_Pal_sprite *target_pal_default;
|
|
@ -18,8 +18,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
#include "SLK_draw_rgb_i.h"
|
||||
//-------------------------------------
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#define _SLK_DRAW_RGB_I_H_
|
||||
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
|
||||
SLK_RGB_sprite *target_rgb;
|
||||
SLK_RGB_sprite *target_rgb_default;
|
|
@ -18,7 +18,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "SLK_input_i.h"
|
||||
#include "SLK_render_i.h"
|
||||
#include "SLK_layer_i.h"
|
|
@ -15,12 +15,12 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
|
||||
//External includes
|
||||
#include <SDL2/SDL.h>
|
||||
#include "../../include/glad/glad.h"
|
||||
#include "../external/glad.h"
|
||||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
#include "SLK_render_i.h"
|
||||
#include "SLK_draw_rgb_i.h"
|
||||
#include "SLK_draw_pal_i.h"
|
||||
|
@ -60,41 +60,33 @@ void SLK_layer_create(unsigned index, int type)
|
|||
switch(type)
|
||||
{
|
||||
case SLK_LAYER_PAL:
|
||||
{
|
||||
layers[index].type_0.target = SLK_pal_sprite_create(screen_width,screen_height);
|
||||
layers[index].type_0.render = SLK_rgb_sprite_create(screen_width,screen_height);
|
||||
|
||||
glGenTextures(1,&layers[index].type_0.texture);
|
||||
glBindTexture(GL_TEXTURE_2D,layers[index].type_0.texture);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
||||
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,screen_width,screen_height,
|
||||
0,GL_RGBA,GL_UNSIGNED_BYTE,layers[index].type_0.render->data);
|
||||
{
|
||||
layers[index].type_0.target = SLK_pal_sprite_create(screen_width,screen_height);
|
||||
layers[index].type_0.render = SLK_rgb_sprite_create(screen_width,screen_height);
|
||||
|
||||
glGenTextures(1,&layers[index].type_0.texture);
|
||||
glBindTexture(GL_TEXTURE_2D,layers[index].type_0.texture);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
||||
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,screen_width,screen_height,
|
||||
0,GL_RGBA,GL_UNSIGNED_BYTE,layers[index].type_0.render->data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SLK_LAYER_RGB:
|
||||
{
|
||||
layers[index].type_1.target = SLK_rgb_sprite_create(screen_width,screen_height);
|
||||
|
||||
glGenTextures(1,&layers[index].type_1.texture);
|
||||
glBindTexture(GL_TEXTURE_2D,layers[index].type_1.texture);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
||||
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,screen_width,screen_height,
|
||||
0,GL_RGBA,GL_UNSIGNED_BYTE,layers[index].type_1.target->data);
|
||||
|
||||
{
|
||||
layers[index].type_1.target = SLK_rgb_sprite_create(screen_width,screen_height);
|
||||
|
||||
glGenTextures(1,&layers[index].type_1.texture);
|
||||
glBindTexture(GL_TEXTURE_2D,layers[index].type_1.texture);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
||||
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,screen_width,screen_height,
|
||||
0,GL_RGBA,GL_UNSIGNED_BYTE,layers[index].type_1.target->data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SLK_LAYER_GPU:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Sets wether the layers is supposed to be drawn.
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#define _SLK_LAYER_I_H_
|
||||
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
|
||||
int dynamic;
|
||||
int layer_count;
|
|
@ -20,8 +20,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
//-------------------------------------
|
||||
|
||||
//#defines
|
|
@ -15,12 +15,12 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
|
||||
//External includes
|
||||
#include <SDL2/SDL.h>
|
||||
#include "../../include/glad/glad.h"
|
||||
#include "../external/glad.h"
|
||||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
#include "SLK_render_i.h"
|
||||
#include "SLK_layer_i.h"
|
||||
//-------------------------------------
|
|
@ -20,8 +20,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
//-------------------------------------
|
||||
|
||||
//#defines
|
|
@ -20,8 +20,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
//-------------------------------------
|
||||
|
||||
//#defines
|
|
@ -20,8 +20,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
//-------------------------------------
|
||||
|
||||
//#defines
|
|
@ -20,13 +20,13 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_types.h"
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_types.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
#include "../external/stb_image.h"
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
#include "../external/stb_image_write.h"
|
||||
//https://github.com/nothings/stb
|
||||
//-------------------------------------
|
||||
|
|
@ -18,7 +18,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||
//-------------------------------------
|
||||
|
||||
//Internal includes
|
||||
#include "../../include/SLK/SLK_functions.h"
|
||||
#include "../include/SLK/SLK_functions.h"
|
||||
//-------------------------------------
|
||||
|
||||
//#defines
|
Loading…
Reference in a new issue