diff --git a/README.md b/README.md index 4283d3a..ddcdb9b 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,11 @@ 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** | 1.46 | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 0.99 | graphics | parse, decode, and rasterize characters from truetype fonts +**stb_image.h** | 1.48 | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_truetype.h** | 1.02 | graphics | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 0.95 | 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_dxt.h** | 1.04 | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor diff --git a/stb_image.h b/stb_image.h index 287eca9..8396ff6 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v1.46 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c +/* stb_image - v1.48 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c when you control the images you're loading no warranty implied; use at your own risk @@ -13,7 +13,7 @@ avoid problematic images and only need the trivial interface JPEG baseline (no JPEG progressive) - PNG 8-bit-per-channel only + PNG 1/2/4/8-bit-per-channel (16 bpc not supported) TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE @@ -28,18 +28,16 @@ - overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) Latest revisions: + 1.48 (2014-12-14) fix incorrectly-named assert() + 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 1.44 (2014-08-07) warnings 1.43 (2014-07-15) fix MSVC-only bug in 1.42 1.42 (2014-07-09) no _CRT_SECURE_NO_WARNINGS; error-path fixes; STBI_ASSERT 1.41 (2014-06-25) fix search&replace that messed up comments/error messages - 1.40 (2014-06-22) gcc warning - 1.39 (2014-06-15) TGA optimization bugfix, multiple BMP fixes - 1.38 (2014-06-06) suppress MSVC run-time warnings, fix accidental rename of 'skip' - 1.37 (2014-06-04) remove duplicate typedef - 1.36 (2014-06-03) converted to header file, allow reading incorrect iphoned-images without iphone flag - 1.35 (2014-05-27) warnings, bugfixes, TGA optimization, etc See end of file for full revision history. @@ -63,7 +61,7 @@ James "moose2000" Brown (iPhone PNG) David Woo Ben "Disch" Wenger (io callbacks) Roy Eltham Martin "SpartanJ" Golini Luke Graham - Thomas Ruf + Omar Cornut (1/2/4-bit png) Thomas Ruf John Bartholomew Optimizations & bugfixes Ken Hamada Fabian "ryg" Giesen Cort Stratton @@ -588,7 +586,7 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp #ifndef STBI_NO_STDIO -FILE *stbi__fopen(char const *filename, char const *mode) +static FILE *stbi__fopen(char const *filename, char const *mode) { FILE *f; #if defined(_MSC_VER) && _MSC_VER >= 1400 @@ -632,7 +630,7 @@ STBIDEF unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int return stbi_load_main(&s,x,y,comp,req_comp); } -unsigned char *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +STBIDEF unsigned char *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); @@ -641,7 +639,7 @@ unsigned char *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *use #ifndef STBI_NO_HDR -float *stbi_loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static float *stbi_loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { unsigned char *data; #ifndef STBI_NO_HDR @@ -654,14 +652,14 @@ float *stbi_loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); } -float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi_loadf_main(&s,x,y,comp,req_comp); } -float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); @@ -669,7 +667,7 @@ float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int } #ifndef STBI_NO_STDIO -float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) { float *result; FILE *f = stbi__fopen(filename, "rb"); @@ -679,7 +677,7 @@ float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) return result; } -float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_file(&s,f); @@ -2040,7 +2038,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) // DEFLATE spec for generating codes memset(sizes, 0, sizeof(sizes)); - memset(z->fast, 255, sizeof(z->fast)); + memset(z->fast, 0, sizeof(z->fast)); for (i=0; i < num; ++i) ++sizes[sizelist[i]]; sizes[0] = 0; @@ -2063,12 +2061,13 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) int s = sizelist[i]; if (s) { int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); z->size [c] = (stbi_uc ) s; z->value[c] = (stbi__uint16) i; if (s <= STBI__ZFAST_BITS) { int k = stbi__bit_reverse(next_code[s],s); while (k < (1 << STBI__ZFAST_BITS)) { - z->fast[k] = (stbi__uint16) c; + z->fast[k] = fastv; k += (1 << s); } } @@ -2123,18 +2122,9 @@ stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) return k; } -stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) { int b,s,k; - if (a->num_bits < 16) stbi__fill_bits(a); - b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; - if (b < 0xffff) { - s = z->size[b]; - a->code_buffer >>= s; - a->num_bits -= s; - return z->value[b]; - } - // not resolved by fast table, so compute it the slow way // use jpeg approach, which requires MSbits at top k = stbi__bit_reverse(a->code_buffer, 16); @@ -2150,10 +2140,25 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) return z->value[b]; } -static int stbi__zexpand(stbi__zbuf *z, int n) // need to make room for n bytes +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); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes { char *q; int cur, limit; + z->zout = zout; if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); cur = (int) (z->zout - z->zout_start); limit = (int) (z->zout_end - z->zout_start); @@ -2183,16 +2188,23 @@ static int stbi__zdist_extra[32] = static int stbi__parse_huffman_block(stbi__zbuf *a) { + char *zout = a->zout; for(;;) { int z = stbi__zhuffman_decode(a, &a->z_length); if (z < 256) { if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes - if (a->zout >= a->zout_end) if (!stbi__zexpand(a, 1)) return 0; - *a->zout++ = (char) z; + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; } else { stbi_uc *p; int len,dist; - if (z == 256) return 1; + if (z == 256) { + a->zout = zout; + return 1; + } z -= 257; len = stbi__zlength_base[z]; if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); @@ -2200,11 +2212,18 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); - if (a->zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); - if (a->zout + len > a->zout_end) if (!stbi__zexpand(a, len)) return 0; - p = (stbi_uc *) (a->zout - dist); - while (len--) - *a->zout++ = *p++; + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + do *zout++ = v; while (--len); + } else { + do *zout++ = *p++; while (--len); + } } } } @@ -2277,7 +2296,7 @@ static int stbi__parse_uncomperssed_block(stbi__zbuf *a) if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); if (a->zout + len > a->zout_end) - if (!stbi__zexpand(a, len)) return 0; + if (!stbi__zexpand(a, a->zout, len)) return 0; memcpy(a->zout, a->zbuffer, len); a->zbuffer += len; a->zout += len; @@ -2441,8 +2460,6 @@ typedef struct stbi__uint32 type; } stbi__pngchunk; -#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) - static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) { stbi__pngchunk c; @@ -2468,13 +2485,23 @@ typedef struct enum { - STBI__F_none=0, STBI__F_sub=1, STBI__F_up=2, STBI__F_avg=3, STBI__F_paeth=4, - STBI__F_avg_first, STBI__F_paeth_first + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first }; static stbi_uc first_row_filter[5] = { - STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, STBI__F_paeth_first + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first }; static int stbi__paeth(int a, int b, int c) @@ -2490,30 +2517,50 @@ static int stbi__paeth(int a, int b, int c) #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings +static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + // create the png data from post-deflated data -static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y) +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { stbi__context *s = a->s; stbi__uint32 i,j,stride = x*out_n; + stbi__uint32 img_len, img_width_bytes; int k; int img_n = s->img_n; // copy it into a local for later + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc(x * y * out_n); + a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); + + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; if (s->img_x == x && s->img_y == y) { - if (raw_len != (img_n * x + 1) * y) return stbi__err("not enough pixels","Corrupt PNG"); + if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); } else { // interlaced: - if (raw_len < (img_n * x + 1) * y) return stbi__err("not enough pixels","Corrupt PNG"); + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); } + for (j=0; j < y; ++j) { stbi_uc *cur = a->out + stride*j; stbi_uc *prior = cur - stride; int filter = *raw++; - if (filter > 4) return stbi__err("invalid filter","Corrupt PNG"); + int filter_bytes = img_n; + int width = x; + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + 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; + } + // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; - // handle first pixel explicitly - for (k=0; k < img_n; ++k) { + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { switch (filter) { case STBI__F_none : cur[k] = raw[k]; break; case STBI__F_sub : cur[k] = raw[k]; break; @@ -2524,26 +2571,37 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r case STBI__F_paeth_first: cur[k] = raw[k]; break; } } - if (img_n != out_n) cur[img_n] = 255; - raw += img_n; - cur += out_n; - prior += out_n; + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else { + raw += 1; + cur += 1; + prior += 1; + } + // this is a little gross, so that we don't switch per-pixel or per-component - if (img_n == out_n) { + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*img_n; #define CASE(f) \ case f: \ - for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \ - for (k=0; k < img_n; ++k) + for (k=0; k < nk; ++k) switch (filter) { - CASE(STBI__F_none) cur[k] = raw[k]; break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-img_n]); break; + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-img_n])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-img_n] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-img_n],0,0)); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; } #undef CASE + raw += nk; } else { STBI_ASSERT(img_n+1 == out_n); #define CASE(f) \ @@ -2562,15 +2620,90 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r #undef CASE } } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + // insert alpha = 255 + stbi_uc *cur = a->out + stride*j; + int i; + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + cur[i*2+1] = 255; + cur[i*2+0] = cur[i]; + } + } else { + assert(img_n == 3); + for (i=x-1; i >= 0; --i) { + cur[i*4+3] = 255; + cur[i*4+2] = cur[i*3+2]; + cur[i*4+1] = cur[i*3+1]; + cur[i*4+0] = cur[i*3+0]; + } + } + } + } + } + return 1; } -static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, int interlaced) +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) { stbi_uc *final; int p; if (!interlaced) - return stbi__create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y); + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); // de-interlacing final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); @@ -2584,17 +2717,22 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_l x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; if (x && y) { - if (!stbi__create_png_image_raw(a, raw, raw_len, out_n, x, y)) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { free(final); return 0; } - for (j=0; j < y; ++j) - for (i=0; i < x; ++i) - memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n, + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, a->out + (j*x+i)*out_n, out_n); + } + } free(a->out); - raw += (x*out_n+1)*y; - raw_len -= (x*out_n+1)*y; + image_data += img_len; + image_data_len -= img_len; } } a->out = final; @@ -2719,12 +2857,14 @@ static void stbi__de_iphone(stbi__png *z) } } +#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { stbi_uc palette[1024], pal_img_n=0; stbi_uc has_trans=0, tc[3]; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; - int first=1,k,interlace=0, is_iphone=0; + int first=1,k,interlace=0, color=0, depth=0, is_iphone=0; stbi__context *s = z->s; z->expanded = NULL; @@ -2738,18 +2878,18 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) for (;;) { stbi__pngchunk c = stbi__get_chunk_header(s); switch (c.type) { - case PNG_TYPE('C','g','B','I'): + case STBI__PNG_TYPE('C','g','B','I'): is_iphone = 1; stbi__skip(s, c.length); break; - case PNG_TYPE('I','H','D','R'): { - int depth,color,comp,filter; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; 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?)"); - depth = stbi__get8(s); if (depth != 8) return stbi__err("8bit only","PNG not supported: 8-bit only"); + depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); @@ -2770,7 +2910,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) break; } - case PNG_TYPE('P','L','T','E'): { + case STBI__PNG_TYPE('P','L','T','E'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); pal_len = c.length / 3; @@ -2784,7 +2924,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) break; } - case PNG_TYPE('t','R','N','S'): { + case STBI__PNG_TYPE('t','R','N','S'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); if (pal_img_n) { @@ -2799,12 +2939,12 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; for (k=0; k < s->img_n; ++k) - tc[k] = (stbi_uc) (stbi__get16be(s) & 255); // non 8-bit images will be larger + tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger } break; } - case PNG_TYPE('I','D','A','T'): { + case STBI__PNG_TYPE('I','D','A','T'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } @@ -2821,19 +2961,21 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) break; } - case PNG_TYPE('I','E','N','D'): { + case STBI__PNG_TYPE('I','E','N','D'): { stbi__uint32 raw_len; if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (scan != SCAN_load) return 1; if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); - z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, 16384, (int *) &raw_len, !is_iphone); + // initial guess for decoded data size to avoid unnecessary reallocs + raw_len = s->img_x * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); if (z->expanded == NULL) return 0; // zlib should set error free(z->idata); z->idata = NULL; if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) s->img_out_n = s->img_n+1; else s->img_out_n = s->img_n; - if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0; if (has_trans) if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) @@ -4685,12 +4827,16 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) 1.46 (2014-08-26) fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG 1.45 (2014-08-16) fix MSVC-ARM internal compiler error by wrapping malloc 1.44 (2014-08-07) - various warning fixes from Ronny Chevalier + various warning fixes from Ronny Chevalier 1.43 (2014-07-15) fix MSVC-only compiler problem in code changed in 1.42 1.42 (2014-07-09) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index 373b105..dcc9d88 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.02 - public domain - rectangle packing +// stb_rect_pack.h - v0.05 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -19,7 +19,12 @@ // Please note: better rectangle packers are welcome! Please // implement them to the same API, but with a different init // function. - +// +// Version history: +// +// 0.05: added STBRP_ASSERT to allow replacing assert +// 0.04: fixed minor bug in STBRP_LARGE_RECTS support +// 0.01: initial release ////////////////////////////////////////////////////////////////////////////// // @@ -29,6 +34,8 @@ #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 @@ -164,6 +171,11 @@ struct stbrp_context #ifdef STB_RECT_PACK_IMPLEMENTATION #include +#ifndef STBRP_ASSERT +#include +#define STBRP_ASSERT assert +#endif + enum { STBRP__INIT_skyline = 1, @@ -173,11 +185,11 @@ STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) { switch (context->init_mode) { case STBRP__INIT_skyline: - assert(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); + STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); context->heuristic = heuristic; break; default: - assert(0); + STBRP_ASSERT(0); } } @@ -205,7 +217,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, { int i; #ifndef STBRP_LARGE_RECTS - assert(width <= 0xffff && height <= 0xffff); + STBRP_ASSERT(width <= 0xffff && height <= 0xffff); #endif for (i=0; i < num_nodes-1; ++i) @@ -224,7 +236,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, context->extra[0].x = 0; context->extra[0].y = 0; context->extra[0].next = &context->extra[1]; - context->extra[1].x = width; + context->extra[1].x = (stbrp_coord) width; #ifdef STBRP_LARGE_RECTS context->extra[1].y = (1<<30); #else @@ -239,17 +251,17 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0 stbrp_node *node = first; int x1 = x0 + width; int min_y, visited_width, waste_area; - assert(first->x <= x0); + STBRP_ASSERT(first->x <= x0); #if 0 // skip in case we're past the node while (node->next->x <= x0) ++node; #else - assert(node->next->x > x0); // we ended up handling this in the caller for efficiency + STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency #endif - assert(node->x <= x0); + STBRP_ASSERT(node->x <= x0); min_y = 0; waste_area = 0; @@ -296,7 +308,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt // align to multiple of c->align width = (width + c->align - 1); width -= width % c->align; - assert(width % c->align == 0); + STBRP_ASSERT(width % c->align == 0); node = c->active_head; prev = &c->active_head; @@ -353,19 +365,19 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt while (tail) { int xpos = tail->x - width; int y,waste; - assert(xpos >= 0); + STBRP_ASSERT(xpos >= 0); // find the left position that matches this while (node->next->x <= xpos) { prev = &node->next; node = node->next; } - assert(node->next->x > xpos && node->x <= xpos); + 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; - assert(y <= best_y); + STBRP_ASSERT(y <= best_y); best_y = y; best_waste = waste; best = prev; @@ -399,8 +411,8 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i // on success, create new node node = context->free_head; - node->x = res.x; - node->y = res.y + height; + node->x = (stbrp_coord) res.x; + node->y = (stbrp_coord) (res.y + height); context->free_head = node->next; @@ -432,15 +444,15 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i node->next = cur; if (cur->x < res.x + width) - cur->x = res.x+width; + cur->x = (stbrp_coord) (res.x + width); #ifdef _DEBUG cur = context->active_head; while (cur->x < context->width) { - assert(cur->x < cur->next->x); + STBRP_ASSERT(cur->x < cur->next->x); cur = cur->next; } - assert(cur->next == NULL); + STBRP_ASSERT(cur->next == NULL); { stbrp_node *L1 = NULL, *L2 = NULL; @@ -457,7 +469,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i cur = cur->next; ++count; } - assert(count == context->num_nodes+2); + STBRP_ASSERT(count == context->num_nodes+2); } #endif @@ -493,6 +505,12 @@ static int rect_original_order(const void *a, const void *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 void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { int i; @@ -501,7 +519,7 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n for (i=0; i < num_rects; ++i) { rects[i].was_packed = i; #ifndef STBRP_LARGE_RECTS - assert(rects[i].w <= 0xffff && rects[i].h <= 0xffff); + STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff); #endif } @@ -514,7 +532,7 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n rects[i].x = (stbrp_coord) fr.x; rects[i].y = (stbrp_coord) fr.y; } else { - rects[i].x = rects[i].y = 0xffff; + rects[i].x = rects[i].y = STBRP__MAXVAL; } } @@ -523,6 +541,6 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n // set was_packed flags for (i=0; i < num_rects; ++i) - rects[i].was_packed = !(rects[i].x == 0xffff && rects[i].y == 0xffff); + rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); } #endif diff --git a/stb_tilemap_editor.h b/stb_tilemap_editor.h index 161b0d7..ed56a10 100644 --- a/stb_tilemap_editor.h +++ b/stb_tilemap_editor.h @@ -1971,14 +1971,14 @@ static int stbte__float_control(int x0, int y0, int w, float minv, float maxv, f stbte__ui.accum_y -= ay*STBTE_FLOAT_CONTROL_GRANULARITY; if (stbte__ui.shift) { if (stbte__ui.active_event == STBTE__leftdown) - delta = ax * 16 + ay; + delta = ax * 16.0f + ay; else - delta = ax / 16.0 + ay / 256.0; + delta = ax / 16.0f + ay / 256.0f; } else { if (stbte__ui.active_event == STBTE__leftdown) - delta = ax*10 + ay; + delta = ax*10.0f + ay; else - delta = ax * 0.1 + ay * 0.01; + delta = ax * 0.1f + ay * 0.01f; } v += delta * scale; if (v < minv) v = minv; @@ -3553,8 +3553,8 @@ static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h) int flag = (int) p[i]; if (stbte__layerbutton(x,y, flag ? 'x' : ' ', STBTE__ID(STBTE__prop_flag,i), flag, 0, 2)) { stbte__begin_undo(tm); - stbte__undo_record_prop_float(tm,mx,my,i,flag); - p[i] = !flag; + stbte__undo_record_prop_float(tm,mx,my,i,(float) flag); + p[i] = (float) !flag; stbte__end_undo(tm); } stbte__draw_text(x+13,y+1,s,x1-(x+13)-2,STBTE__TEXTCOLOR(STBTE__cpanel)); @@ -3568,7 +3568,7 @@ static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h) if (a+v != p[i] || v < 0 || v > b-a) { if (v < 0) v = 0; if (v > b-a) v = b-a; - p[i] = a+v; // @TODO undo + p[i] = (float) (a+v); // @TODO undo } switch (stbte__slider(x, slider_width, y+7, b-a, &v, STBTE__ID(STBTE__prop_int,i))) { @@ -3576,7 +3576,7 @@ static void stbte__props_panel(stbte_tilemap *tm, int x0, int y0, int w, int h) stbte__saved = p[i]; // fallthrough case STBTE__change: - p[i] = a+v; // @TODO undo + p[i] = (float) (a+v); // @TODO undo break; case STBTE__end: if (p[i] != stbte__saved) { diff --git a/stb_truetype.h b/stb_truetype.h index 1c0ab4b..56ef47b 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v0.99 - public domain +// stb_truetype.h - v1.02 - public domain // authored from 2009-2014 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -35,8 +35,15 @@ // Hou Qiming // Fabian "ryg" Giesen // +// Misc other: +// Ryan Gordon +// // VERSION HISTORY // +// 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 +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID // 0.8b (2014-07-07) fix a warning @@ -58,7 +65,7 @@ // updated Hello World! sample to use kerning and subpixel // fixed some warnings // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) -// userdata, malloc-from-userdata, non-zero fill (STB) +// userdata, malloc-from-userdata, non-zero fill (stb) // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // @@ -76,11 +83,18 @@ // before the #include of this file. This expands out the actual // implementation into that C/C++ file. // -// Simple 3D API (don't ship this, but it's fine for tools and quick start, -// and you can cut and paste from it to move to more advanced) +// Simple 3D API (don't ship this, but it's fine for tools and quick start) // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture // stbtt_GetBakedQuad() -- compute quad to draw for a given char // +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversample() -- for improved quality on small fonts +// stbtt_PackFontRanges() +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// // "Load" a font file from a memory buffer (you have to keep the buffer loaded) // stbtt_InitFont() // stbtt_GetFontOffsetForIndex() -- use for TTC font collections @@ -428,7 +442,7 @@ extern "C" { typedef struct { unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; + float xoff,yoff,xadvance; } stbtt_bakedchar; extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) @@ -463,6 +477,100 @@ extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // sa // It's inefficient; you might want to c&p it and optimize it. + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; + +extern int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is weight x height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is // the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +extern void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +extern int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_char_in_range; + int num_chars_in_range; + stbtt_packedchar *chardata_for_range; // output +} stbtt_pack_range; + +extern int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. + + +extern void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s). The default (no oversampling) is achieved by +// h_oversample=1, v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts + +extern void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + ////////////////////////////////////////////////////////////////////////////// // // FONT LOADING @@ -770,6 +878,12 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC #ifdef STB_TRUETYPE_IMPLEMENTATION +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file @@ -1880,7 +1994,8 @@ extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font float scale; int x,y,bottom_y, i; stbtt_fontinfo f; - stbtt_InitFont(&f, data, offset); + if (!stbtt_InitFont(&f, data, offset)) + return -1; STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels x=y=1; bottom_y = 1; @@ -1908,9 +2023,9 @@ extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font chardata[i].xadvance = scale * advance; chardata[i].xoff = (float) x0; chardata[i].yoff = (float) y0; - x = x + gw + 2; - if (y+gh+2 > bottom_y) - bottom_y = y+gh+2; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; } return bottom_y; } @@ -1936,6 +2051,404 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde *xpos += b->xadvance; } +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +typedef struct +{ + stbrp_coord x,y; + int id,w,h,was_packed; +} stbrp_rect; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + for (j=0; j < h; ++j) { + int i; + unsigned int total; + memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + for (j=0; j < w; ++j) { + int i; + unsigned int total; + memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + float recip_h = 1.0f / spc->h_oversample; + float recip_v = 1.0f / spc->v_oversample; + float sub_x = stbtt__oversample_shift(spc->h_oversample); + float sub_y = stbtt__oversample_shift(spc->v_oversample); + int i,j,k,n, return_value = 1; + stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars_in_range; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars_in_range; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh); + for (j=0; j < ranges[i].num_chars_in_range; ++j) { + int x0,y0,x1,y1; + stbtt_GetCodepointBitmapBoxSubpixel(&info, ranges[i].first_unicode_char_in_range + j, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + ++k; + } + } + + stbrp_pack_rects(context, rects, k); + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh); + for (j=0; j < ranges[i].num_chars_in_range; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(&info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + return return_value; +} + +int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_char_in_range = first_unicode_char_in_range; + range.num_chars_in_range = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + + ////////////////////////////////////////////////////////////////////////////// // // font name matching -- recommended not to use this diff --git a/tests/c_lexer_test.dsp b/tests/c_lexer_test.dsp index d21c8a5..13f8758 100644 --- a/tests/c_lexer_test.dsp +++ b/tests/c_lexer_test.dsp @@ -64,7 +64,8 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug\c_lexer_test" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/tests/image_test.c b/tests/image_test.c index c17c766..5971704 100644 --- a/tests/image_test.c +++ b/tests/image_test.c @@ -7,6 +7,8 @@ #define STB_DEFINE #include "stb.h" +#define PNGSUITE_PRIMARY + int main(int argc, char **argv) { int w,h; @@ -31,25 +33,60 @@ int main(int argc, char **argv) printf("FAILED 4\n"); } } else { - int i; + int i, nope=0; + #ifdef PNGSUITE_PRIMARY + char **files = stb_readdir_files("pngsuite/primary"); + #else char **files = stb_readdir_files("images"); + #endif for (i=0; i < stb_arr_len(files); ++i) { int n; + char **failed = NULL; unsigned char *data; - printf("%s\n", files[i]); - data = stbi_load(files[i], &w, &h, &n, 4); if (data) free(data); else printf("Failed &n\n"); - data = stbi_load(files[i], &w, &h, 0, 1); if (data) free(data); else printf("Failed 1\n"); - data = stbi_load(files[i], &w, &h, 0, 2); if (data) free(data); else printf("Failed 2\n"); - data = stbi_load(files[i], &w, &h, 0, 3); if (data) free(data); else printf("Failed 3\n"); - data = stbi_load(files[i], &w, &h, 0, 4); + printf("."); + //printf("%s\n", files[i]); + data = stbi_load(files[i], &w, &h, &n, 0); if (data) free(data); else stb_arr_push(failed, "&n"); + data = stbi_load(files[i], &w, &h, 0, 1); if (data) free(data); else stb_arr_push(failed, "1"); + data = stbi_load(files[i], &w, &h, 0, 2); if (data) free(data); else stb_arr_push(failed, "2"); + data = stbi_load(files[i], &w, &h, 0, 3); if (data) free(data); else stb_arr_push(failed, "3"); + data = stbi_load(files[i], &w, &h, 0, 4); if (data) ; else stb_arr_push(failed, "4"); if (data) { char fname[512]; + + #ifdef PNGSUITE_PRIMARY + int w2,h2; + unsigned char *data2; + stb_splitpath(fname, files[i], STB_FILE_EXT); + data2 = stbi_load(stb_sprintf("pngsuite/primary_check/%s", fname), &w2, &h2, 0, 4); + if (!data2) + printf("FAILED: couldn't load 'pngsuite/primary_check/%s\n", fname); + else { + if (w != w2 || h != w2 || 0 != memcmp(data, data2, w*h*4)) { + int x,y,c; + if (w == w2 && h == h2) + for (y=0; y < h; ++y) + for (x=0; x < w; ++x) + for (c=0; c < 4; ++c) + assert(data[y*w*4+x*4+c] == data2[y*w*4+x*4+c]); + printf("FAILED: %s loaded but didn't match PRIMARY_check 32-bit version\n", files[i]); + } + free(data2); + } + #else stb_splitpath(fname, files[i], STB_FILE); stbi_write_png(stb_sprintf("output/%s.png", fname), w, h, 4, data, w*4); + #endif free(data); - } else - printf("FAILED\n"); + } + if (failed) { + int j; + printf("FAILED: "); + for (j=0; j < stb_arr_len(failed); ++j) + printf("%s ", failed[j]); + printf(" -- %s\n", files[i]); + } } + printf("Tested %d files.\n", i); } return 0; } diff --git a/tests/image_test.dsp b/tests/image_test.dsp index 5cabd09..840ea16 100644 --- a/tests/image_test.dsp +++ b/tests/image_test.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -64,7 +64,8 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug\image_test" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/tests/oversample/README.md b/tests/oversample/README.md new file mode 100644 index 0000000..cdfdfff --- /dev/null +++ b/tests/oversample/README.md @@ -0,0 +1,94 @@ +# Font character oversampling for rendering from atlas textures + +TL,DR: Run oversample.exe on a windows machine to see the +benefits of oversampling. It will try to use arial.ttf from the +Windows font directory unless you type the name of a .ttf file as +a command-line argument. + +## Benefits of oversampling + +Oversampling is a mechanism for improving subpixel rendering of characters. + +Improving subpixel has a few benefits: + +* With horizontal-oversampling, text can remain sharper while still being sub-pixel positioned for better kerning +* Horizontally-oversampled text significantly reduces aliasing when text animates horizontally +* Vertically-oversampled text significantly reduces aliasing when text animates vertically +* Text oversampled in both directions significantly reduces aliasing when text rotates + +## What text oversampling is + +A common strategy for rendering text is to cache character bitmaps +and reuse them. For hinted characters, every instance of a given +character is always identical, so this works fine. However, stb_truetype +doesn't do hinting. + +For anti-aliased characters, you can actually position the characters +with subpixel precision, and get different bitmaps based on that positioning +if you re-render the vector data. + +However, if you simply cache a single version of the bitmap and +draw it at different subpixel positions with a GPU, you will get +either the exact same result (if you use point-sampling on the +texture) or linear filtering. Linear filtering will cause a sub-pixel +positioned bitmap to blur further, causing a visible de-sharpening +of the character. (And, since the character wasn't hinted, it was +already blurrier than a hinted one would be, and now it gets even +more blurry.) + +You can avoid this by caching multiple variants of a character which +were rendered independently from the vector data. For example, you +might cache 3 versions of a char, at 0, 1/3, and 2/3rds of a pixel +horizontal offset, and always require characters to fall on integer +positions vertically. + +When creating a texture atlas for use on GPUs, which support bilinear +filtering, there is a better approach than caching several independent +positions, which is to allow lerping between the versions to allow +finer subpixel positioning. You can achieve these by interleaving +each of the cached bitmaps, but this turns out to be mathematically +equivalent to a simpler operation: oversampling and prefiltering the +characters. + +So, setting oversampling of 2x2 in stb_truetype is equivalent to caching +each character in 4 different variations, 1 for each subpixel position +in a 2x2 set. + +An advantage of this formulation is that no changes are required to +the rendering code; the exact same quad-rendering code works, it just +uses different texture coordinates. (Note this does potentially increase +texture bandwidth for text rendering since we end up minifying the texture +without using mipmapping, but you probably are not going to be fill-bound +by your text rendering.) + +## What about gamma? + +Gamma-correction for fonts just doesn't work. This doesn't seem to make +much sense -- it's physically correct, it simulates what we'd see if you +shrunk a font down really far, right? + +But you can play with it in the oversample.exe app. If you turn it on, +white-on-black fonts become too thick (i.e. they become too bright), and +black-on-white fonts become too thin (i.e. they are insufficiently dark). There is +no way to adjust the font's inherent thickness (i.e. by switching to +bold) to fix this for both; making the font thicker will make white +text worse, and making the font thinner will make black text worse. +Obviously you could use different fonts for light and dark cases, but +this doesn't seem like a very good way for fonts to work. + +Multiple people who have experimented with this independently (me, +Fabian Giesen,and Maxim Shemanarev of Anti-Grain Geometry) have all +concluded that correct gamma-correction does not produce the best +results for fonts. Font rendering just generally looks better without +gamma correction (or possibly with some arbitrary power stuck in +there, but it's not really correcting for gamma at that point). Maybe +this is in part a product of how we're used to fonts being on screens +which has changed how we expect them to look (e.g. perhaps hinting +oversharpens them and prevents the real-world thinning you'd see in +a black-on-white text). + +(AGG link on text rendering, including mention of gamma: + http://www.antigrain.com/research/font_rasterization/ ) + +Nevertheless, even if you turn on gamma-correction, you will find that +oversampling still helps in many cases for small fonts. diff --git a/tests/oversample/main.c b/tests/oversample/main.c new file mode 100644 index 0000000..bc6bd0f --- /dev/null +++ b/tests/oversample/main.c @@ -0,0 +1,332 @@ +#pragma warning(disable:4244; disable:4305; disable:4018) +#include +#include + +#define STB_WINMAIN +#include "stb_wingraph.h" + +#define STB_TRUETYPE_IMPLEMENTATION +#define STB_RECT_PACK_IMPLEMENTATION +#include "stb_rect_pack.h" +#include "stb_truetype.h" + +#ifndef WINGDIAPI +#define CALLBACK __stdcall +#define WINGDIAPI __declspec(dllimport) +#define APIENTRY __stdcall +#endif + +#include +#include + +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 + +#define SIZE_X 1024 +#define SIZE_Y 768 + +stbtt_packedchar chardata[6][128]; + +int sx=SIZE_X, sy=SIZE_Y; + +#define BITMAP_W 512 +#define BITMAP_H 512 +unsigned char temp_bitmap[BITMAP_W][BITMAP_H]; +unsigned char ttf_buffer[1 << 25]; +GLuint font_tex; + +float scale[2] = { 24.0f, 14.0f }; + +int sf[6] = { 0,1,2, 0,1,2 }; + +void load_fonts(void) +{ + stbtt_pack_context pc; + int i; + FILE *f; + char filename[256]; + char *win = getenv("windir"); + if (win == NULL) win = getenv("SystemRoot"); + + f = fopen(stb_wingraph_commandline, "rb"); + if (!f) { + if (win == NULL) + sprintf(filename, "arial.ttf", win); + else + sprintf(filename, "%s/fonts/arial.ttf", win); + f = fopen(filename, "rb"); + if (!f) exit(0); + } + + fread(ttf_buffer, 1, 1<<25, f); + + stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL); + for (i=0; i < 2; ++i) { + stbtt_PackSetOversampling(&pc, 1, 1); + stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+0]+32); + stbtt_PackSetOversampling(&pc, 2, 2); + stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+1]+32); + stbtt_PackSetOversampling(&pc, 3, 1); + stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+2]+32); + } + stbtt_PackEnd(&pc); + + glGenTextures(1, &font_tex); + glBindTexture(GL_TEXTURE_2D, font_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +} + +int black_on_white; + +void draw_init(void) +{ + glDisable(GL_CULL_FACE); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glViewport(0,0,sx,sy); + if (black_on_white) + glClearColor(255,255,255,0); + else + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0,sx,sy,0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +void drawBoxTC(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1) +{ + glTexCoord2f(s0,t0); glVertex2f(x0,y0); + glTexCoord2f(s1,t0); glVertex2f(x1,y0); + glTexCoord2f(s1,t1); glVertex2f(x1,y1); + glTexCoord2f(s0,t1); glVertex2f(x0,y1); +} + +int integer_align; + +void print(float x, float y, int font, char *text) +{ + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, font_tex); + glBegin(GL_QUADS); + while (*text) { + stbtt_aligned_quad q; + stbtt_GetPackedQuad(chardata[font], BITMAP_W, BITMAP_H, *text++, &x, &y, &q, font ? 0 : integer_align); + drawBoxTC(q.x0,q.y0,q.x1,q.y1, q.s0,q.t0,q.s1,q.t1); + } + glEnd(); +} + +int font=3; +int translating; +int rotating=0; +int srgb=0; +float rotate_t, translate_t; +int show_tex; + +void draw_world(void) +{ + int sfont = sf[font]; + float x = 20; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (black_on_white) + glColor3f(0,0,0); + else + glColor3f(1,1,1); + + + print(80, 30, sfont, "Controls:"); + print(100, 60, sfont, "S: toggle font size"); + print(100, 85, sfont, "O: toggle oversampling"); + print(100,110, sfont, "T: toggle translation"); + print(100,135, sfont, "R: toggle rotation"); + print(100,160, sfont, "P: toggle pixel-snap (only non-oversampled)"); + print(100,185, sfont, "G: toggle srgb gamma-correction"); + if (black_on_white) + print(100,210, sfont, "B: toggle to white-on-black"); + else + print(100,210, sfont, "B: toggle to black-on-white"); + print(100,235, sfont, "V: view font texture"); + + print(80, 300, sfont, "Current font:"); + + if (!show_tex) { + if (font < 3) + print(100, 350, sfont, "Font height: 24 pixels"); + else + print(100, 350, sfont, "Font height: 14 pixels"); + } + + if (font%3==1) + print(100, 325, sfont, "2x2 oversampled text at 1:1"); + else if (font%3 == 2) + print(100, 325, sfont, "3x1 oversampled text at 1:1"); + else if (integer_align) + print(100, 325, sfont, "1:1 text, one texel = one pixel, snapped to integer coordinates"); + else + print(100, 325, sfont, "1:1 text, one texel = one pixel"); + + if (show_tex) { + glBegin(GL_QUADS); + drawBoxTC(200,400, 200+BITMAP_W,300+BITMAP_H, 0,0,1,1); + glEnd(); + } else { + glMatrixMode(GL_MODELVIEW); + glTranslatef(200,350,0); + + if (translating) + x += fmod(translate_t*8,30); + + if (rotating) { + glTranslatef(100,150,0); + glRotatef(rotate_t*2,0,0,1); + glTranslatef(-100,-150,0); + } + print(x,100, font, "This is a test"); + print(x,130, font, "Now is the time for all good men to come to the aid of their country."); + print(x,160, font, "The quick brown fox jumps over the lazy dog."); + print(x,190, font, "0123456789"); + } +} + +void draw(void) +{ + draw_init(); + draw_world(); + stbwingraph_SwapBuffers(NULL); +} + +static int initialized=0; +static float last_dt; + +int move[4]; +int raw_mouse_x, raw_mouse_y; + +int loopmode(float dt, int real, int in_client) +{ + float actual_dt = dt; + + if (!initialized) return 0; + + rotate_t += dt; + translate_t += dt; + +// music_sim(); + if (!real) + return 0; + + if (dt > 0.25) dt = 0.25; + if (dt < 0.01) dt = 0.01; + + draw(); + + return 0; +} + +int winproc(void *data, stbwingraph_event *e) +{ + switch (e->type) { + case STBWGE_create: + break; + + case STBWGE_char: + switch(e->key) { + case 27: + stbwingraph_ShowCursor(NULL,1); + return STBWINGRAPH_winproc_exit; + break; + case 'o': case 'O': + font = (font+1) % 3 + (font/3)*3; + break; + case 's': case 'S': + font = (font+3) % 6; + break; + case 't': case 'T': + translating = !translating; + translate_t = 0; + break; + case 'r': case 'R': + rotating = !rotating; + rotate_t = 0; + break; + case 'p': case 'P': + integer_align = !integer_align; + break; + case 'g': case 'G': + srgb = !srgb; + if (srgb) + glEnable(GL_FRAMEBUFFER_SRGB_EXT); + else + glDisable(GL_FRAMEBUFFER_SRGB_EXT); + break; + case 'v': case 'V': + show_tex = !show_tex; + break; + case 'b': case 'B': + black_on_white = !black_on_white; + break; + } + break; + + case STBWGE_mousemove: + raw_mouse_x = e->mx; + raw_mouse_y = e->my; + break; + +#if 0 + case STBWGE_mousewheel: do_mouse(e,0,0); break; + case STBWGE_leftdown: do_mouse(e, 1,0); break; + case STBWGE_leftup: do_mouse(e,-1,0); break; + case STBWGE_rightdown: do_mouse(e,0, 1); break; + case STBWGE_rightup: do_mouse(e,0,-1); break; +#endif + + case STBWGE_keydown: + if (e->key == VK_RIGHT) move[0] = 1; + if (e->key == VK_LEFT) move[1] = 1; + if (e->key == VK_UP) move[2] = 1; + if (e->key == VK_DOWN) move[3] = 1; + break; + case STBWGE_keyup: + if (e->key == VK_RIGHT) move[0] = 0; + if (e->key == VK_LEFT) move[1] = 0; + if (e->key == VK_UP) move[2] = 0; + if (e->key == VK_DOWN) move[3] = 0; + break; + + case STBWGE_size: + sx = e->width; + sy = e->height; + loopmode(0,1,0); + break; + + case STBWGE_draw: + if (initialized) + loopmode(0,1,0); + break; + + default: + return STBWINGRAPH_unprocessed; + } + return 0; +} + +void stbwingraph_main(void) +{ + stbwingraph_Priority(2); + stbwingraph_CreateWindow(1, winproc, NULL, "tt", SIZE_X,SIZE_Y, 0, 1, 0, 0); + stbwingraph_ShowCursor(NULL, 0); + load_fonts(); + initialized = 1; + stbwingraph_MainLoop(loopmode, 0.016f); // 30 fps = 0.33 +} + diff --git a/tests/oversample/oversample.dsp b/tests/oversample/oversample.dsp new file mode 100644 index 0000000..cc1edc3 --- /dev/null +++ b/tests/oversample/oversample.dsp @@ -0,0 +1,97 @@ +# Microsoft Developer Studio Project File - Name="oversample" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=oversample - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "oversample.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "oversample.mak" CFG="oversample - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "oversample - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "oversample - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "oversample - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /WX /GX /O2 /I "c:\sean\prj\stb" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# SUBTRACT LINK32 /map /debug + +!ELSEIF "$(CFG)" == "oversample - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /WX /Gm /GX /Zi /Od /I "c:\sean\prj\stb" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib winspool.lib comdlg32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "oversample - Win32 Release" +# Name "oversample - Win32 Debug" +# Begin Source File + +SOURCE=.\main.c +# End Source File +# End Target +# End Project diff --git a/tests/oversample/oversample.dsw b/tests/oversample/oversample.dsw new file mode 100644 index 0000000..0f5aa7f --- /dev/null +++ b/tests/oversample/oversample.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "oversample"=.\oversample.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/tests/oversample/oversample.exe b/tests/oversample/oversample.exe new file mode 100644 index 0000000..0040693 Binary files /dev/null and b/tests/oversample/oversample.exe differ diff --git a/tests/oversample/stb_wingraph.h b/tests/oversample/stb_wingraph.h new file mode 100644 index 0000000..ee16923 --- /dev/null +++ b/tests/oversample/stb_wingraph.h @@ -0,0 +1,827 @@ +// stb_wingraph.h v0.01 - public domain windows graphics programming +// wraps WinMain, ChoosePixelFormat, ChangeDisplayResolution, etc. for +// doing OpenGL graphics +// +// in ONE source file, put '#define STB_DEFINE' before including this +// OR put '#define STB_WINMAIN' to define a WinMain that calls stbwingraph_main(void) +// +// @TODO: +// 2d rendering interface (that can be done easily in software) +// STB_WINGRAPH_SOFTWARE -- 2d software rendering only +// STB_WINGRAPH_OPENGL -- OpenGL only + + +#ifndef INCLUDE_STB_WINGRAPH_H +#define INCLUDE_STB_WINGRAPH_H + +#ifdef STB_WINMAIN + #ifndef STB_DEFINE + #define STB_DEFINE + #define STB_WINGRAPH_DISABLE_DEFINE_AT_END + #endif +#endif + +#ifdef STB_DEFINE + #pragma comment(lib, "opengl32.lib") + #pragma comment(lib, "glu32.lib") + #pragma comment(lib, "winmm.lib") +#endif + +#ifdef __cplusplus +#define STB_EXTERN extern "C" +#else +#define STB_EXTERN +#endif + +#ifdef STB_DEFINE +#ifndef _WINDOWS_ + #ifdef APIENTRY + #undef APIENTRY + #endif + #ifdef WINGDIAPI + #undef WINGDIAPI + #endif + #define _WIN32_WINNT 0x0400 // WM_MOUSEWHEEL + #include +#endif +#include +#include +#include +#include +#include +#endif + +typedef void * stbwingraph_hwnd; +typedef void * stbwingraph_hinstance; + +enum +{ + STBWINGRAPH_unprocessed = -(1 << 24), + STBWINGRAPH_do_not_show, + STBWINGRAPH_winproc_exit, + STBWINGRAPH_winproc_update, + STBWINGRAPH_update_exit, + STBWINGRAPH_update_pause, +}; + +typedef enum +{ + STBWGE__none=0, + + STBWGE_create, + STBWGE_create_postshow, + STBWGE_draw, + STBWGE_destroy, + STBWGE_char, + STBWGE_keydown, + STBWGE_syskeydown, + STBWGE_keyup, + STBWGE_syskeyup, + STBWGE_deactivate, + STBWGE_activate, + STBWGE_size, + + STBWGE_mousemove , + STBWGE_leftdown , STBWGE_leftup , + STBWGE_middledown, STBWGE_middleup, + STBWGE_rightdown , STBWGE_rightup , + STBWGE_mousewheel, +} stbwingraph_event_type; + +typedef struct +{ + stbwingraph_event_type type; + + // for input events (mouse, keyboard) + int mx,my; // mouse x & y + int dx,dy; + int shift, ctrl, alt; + + // for keyboard events + int key; + + // for STBWGE_size: + int width, height; + + // for STBWGE_crate + int did_share_lists; // if true, wglShareLists succeeded + + void *handle; + +} stbwingraph_event; + +typedef int (*stbwingraph_window_proc)(void *data, stbwingraph_event *event); + +extern stbwingraph_hinstance stbwingraph_app; +extern stbwingraph_hwnd stbwingraph_primary_window; +extern int stbwingraph_request_fullscreen; +extern int stbwingraph_request_windowed; + +STB_EXTERN void stbwingraph_ods(char *str, ...); +STB_EXTERN int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, + char *caption, char *text, ...); +STB_EXTERN int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, + unsigned int bits, int use_message_box); +STB_EXTERN int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, + int alpha_bits, int depth_bits, int stencil_bits, int accum_bits); +STB_EXTERN int stbwingraph_DefineClass(void *hinstance, char *iconname); +STB_EXTERN void stbwingraph_SwapBuffers(void *win); +STB_EXTERN void stbwingraph_Priority(int n); + +STB_EXTERN void stbwingraph_MakeFonts(void *window, int font_base); +STB_EXTERN void stbwingraph_ShowWindow(void *window); +STB_EXTERN void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil); +STB_EXTERN void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height); +STB_EXTERN void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh); +STB_EXTERN void stbwingraph_DestroyWindow(void *window); +STB_EXTERN void stbwingraph_ShowCursor(void *window, int visible); +STB_EXTERN float stbwingraph_GetTimestep(float minimum_time); +STB_EXTERN void stbwingraph_SetGLWindow(void *win); +typedef int (*stbwingraph_update)(float timestep, int real, int in_client); +STB_EXTERN int stbwingraph_MainLoop(stbwingraph_update func, float mintime); + +#ifdef STB_DEFINE +stbwingraph_hinstance stbwingraph_app; +stbwingraph_hwnd stbwingraph_primary_window; +int stbwingraph_request_fullscreen; +int stbwingraph_request_windowed; + +void stbwingraph_ods(char *str, ...) +{ + char buffer[1024]; + va_list v; + va_start(v,str); + vsprintf(buffer, str, v); + va_end(v); + OutputDebugString(buffer); +} + +int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, char *caption, char *text, ...) +{ + va_list v; + char buffer[1024]; + va_start(v, text); + vsprintf(buffer, text, v); + va_end(v); + return MessageBox(win, buffer, caption, type); +} + +void stbwingraph_Priority(int n) +{ + int p; + switch (n) { + case -1: p = THREAD_PRIORITY_BELOW_NORMAL; break; + case 0: p = THREAD_PRIORITY_NORMAL; break; + case 1: p = THREAD_PRIORITY_ABOVE_NORMAL; break; + default: + if (n < 0) p = THREAD_PRIORITY_LOWEST; + else p = THREAD_PRIORITY_HIGHEST; + } + SetThreadPriority(GetCurrentThread(), p); +} + +static void stbwingraph_ResetResolution(void) +{ + ChangeDisplaySettings(NULL, 0); +} + +static void stbwingraph_RegisterResetResolution(void) +{ + static int done=0; + if (!done) { + done = 1; + atexit(stbwingraph_ResetResolution); + } +} + +int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, unsigned int bits, int use_message_box) +{ + DEVMODE mode; + int res; + + int i, tries=0; + for (i=0; ; ++i) { + int success = EnumDisplaySettings(NULL, i, &mode); + if (!success) break; + if (mode.dmBitsPerPel == bits && mode.dmPelsWidth == w && mode.dmPelsHeight == h) { + ++tries; + success = ChangeDisplaySettings(&mode, CDS_FULLSCREEN); + if (success == DISP_CHANGE_SUCCESSFUL) { + stbwingraph_RegisterResetResolution(); + return TRUE; + } + break; + } + } + + if (!tries) { + if (use_message_box) + stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits); + return FALSE; + } + + // we tried but failed, so try explicitly doing it without specifying refresh rate + + // Win95 support logic + mode.dmBitsPerPel = bits; + mode.dmPelsWidth = w; + mode.dmPelsHeight = h; + mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + res = ChangeDisplaySettings(&mode, CDS_FULLSCREEN); + + switch (res) { + case DISP_CHANGE_SUCCESSFUL: + stbwingraph_RegisterResetResolution(); + return TRUE; + + case DISP_CHANGE_RESTART: + if (use_message_box) + stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "Please set your desktop to %d-bit color and then try again."); + return FALSE; + + case DISP_CHANGE_FAILED: + if (use_message_box) + stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The hardware failed to change modes."); + return FALSE; + + case DISP_CHANGE_BADMODE: + if (use_message_box) + stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits); + return FALSE; + + default: + if (use_message_box) + stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "An unknown error prevented a change to a %d x %d x %d-bit display.", w, h, bits); + return FALSE; + } +} + +int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, int alpha_bits, int depth_bits, int stencil_bits, int accum_bits) +{ + HDC dc = GetDC(win); + PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd) }; + int pixel_format; + + pfd.nVersion = 1; + pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; + pfd.dwLayerMask = PFD_MAIN_PLANE; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = color_bits; + pfd.cAlphaBits = alpha_bits; + pfd.cDepthBits = depth_bits; + pfd.cStencilBits = stencil_bits; + pfd.cAccumBits = accum_bits; + + pixel_format = ChoosePixelFormat(dc, &pfd); + if (!pixel_format) return FALSE; + + if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) + return FALSE; + SetPixelFormat(dc, pixel_format, &pfd); + + return TRUE; +} + +typedef struct +{ + // app data + stbwingraph_window_proc func; + void *data; + // creation parameters + int color, alpha, depth, stencil, accum; + HWND share_window; + HWND window; + // internal data + HGLRC rc; + HDC dc; + int hide_mouse; + int in_client; + int active; + int did_share_lists; + int mx,my; // last mouse positions +} stbwingraph__window; + +static void stbwingraph__inclient(stbwingraph__window *win, int state) +{ + if (state != win->in_client) { + win->in_client = state; + if (win->hide_mouse) + ShowCursor(!state); + } +} + +static void stbwingraph__key(stbwingraph_event *e, int type, int key, stbwingraph__window *z) +{ + e->type = type; + e->key = key; + e->shift = (GetKeyState(VK_SHIFT) < 0); + e->ctrl = (GetKeyState(VK_CONTROL) < 0); + e->alt = (GetKeyState(VK_MENU) < 0); + if (z) { + e->mx = z->mx; + e->my = z->my; + } else { + e->mx = e->my = 0; + } + e->dx = e->dy = 0; +} + +static void stbwingraph__mouse(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z) +{ + static int captured = 0; + e->type = type; + e->mx = (short) LOWORD(lparam); + e->my = (short) HIWORD(lparam); + if (!z || z->mx == -(1 << 30)) { + e->dx = e->dy = 0; + } else { + e->dx = e->mx - z->mx; + e->dy = e->my - z->my; + } + e->shift = (wparam & MK_SHIFT) != 0; + e->ctrl = (wparam & MK_CONTROL) != 0; + e->alt = (wparam & MK_ALT) != 0; + if (z) { + z->mx = e->mx; + z->my = e->my; + } + if (capture) { + if (!captured && capture == 1) + SetCapture(wnd); + captured += capture; + if (!captured && capture == -1) + ReleaseCapture(); + if (captured < 0) captured = 0; + } +} + +static void stbwingraph__mousewheel(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z) +{ + // lparam seems bogus! + static int captured = 0; + e->type = type; + if (z) { + e->mx = z->mx; + e->my = z->my; + } + e->dx = e->dy = 0; + e->shift = (wparam & MK_SHIFT) != 0; + e->ctrl = (wparam & MK_CONTROL) != 0; + e->alt = (GetKeyState(VK_MENU) < 0); + e->key = ((int) wparam >> 16); +} + +int stbwingraph_force_update; +static int WINAPI stbwingraph_WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + int allow_default = TRUE; + stbwingraph_event e = { STBWGE__none }; + // the following line is wrong for 64-bit windows, but VC6 doesn't have GetWindowLongPtr + stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(wnd, GWL_USERDATA); + + switch (msg) { + + case WM_CREATE: + { + LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam; + assert(z == NULL); + z = (stbwingraph__window *) lpcs->lpCreateParams; + SetWindowLong(wnd, GWL_USERDATA, (LONG) z); + z->dc = GetDC(wnd); + if (stbwingraph_SetPixelFormat(wnd, z->color, z->alpha, z->depth, z->stencil, z->accum)) { + z->rc = wglCreateContext(z->dc); + if (z->rc) { + e.type = STBWGE_create; + z->did_share_lists = FALSE; + if (z->share_window) { + stbwingraph__window *y = (stbwingraph__window *) GetWindowLong(z->share_window, GWL_USERDATA); + if (wglShareLists(z->rc, y->rc)) + z->did_share_lists = TRUE; + } + wglMakeCurrent(z->dc, z->rc); + return 0; + } + } + return -1; + } + + case WM_PAINT: { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(wnd, &ps); + SelectObject(hdc, GetStockObject(NULL_BRUSH)); + e.type = STBWGE_draw; + e.handle = wnd; + z->func(z->data, &e); + EndPaint(wnd, &ps); + return 0; + } + + case WM_DESTROY: + e.type = STBWGE_destroy; + e.handle = wnd; + if (z && z->func) + z->func(z->data, &e); + wglMakeCurrent(NULL, NULL) ; + if (z) { + if (z->rc) wglDeleteContext(z->rc); + z->dc = 0; + z->rc = 0; + } + if (wnd == stbwingraph_primary_window) + PostQuitMessage (0); + return 0; + + case WM_CHAR: stbwingraph__key(&e, STBWGE_char , wparam, z); break; + case WM_KEYDOWN: stbwingraph__key(&e, STBWGE_keydown, wparam, z); break; + case WM_KEYUP: stbwingraph__key(&e, STBWGE_keyup , wparam, z); break; + + case WM_NCMOUSEMOVE: stbwingraph__inclient(z,0); break; + case WM_MOUSEMOVE: stbwingraph__inclient(z,1); stbwingraph__mouse(&e, STBWGE_mousemove, wparam, lparam,0,wnd, z); break; + case WM_LBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_leftdown, wparam, lparam,1,wnd, z); break; + case WM_MBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_middledown, wparam, lparam,1,wnd, z); break; + case WM_RBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_rightdown, wparam, lparam,1,wnd, z); break; + case WM_LBUTTONUP: stbwingraph__mouse(&e, STBWGE_leftup, wparam, lparam,-1,wnd, z); break; + case WM_MBUTTONUP: stbwingraph__mouse(&e, STBWGE_middleup, wparam, lparam,-1,wnd, z); break; + case WM_RBUTTONUP: stbwingraph__mouse(&e, STBWGE_rightup, wparam, lparam,-1,wnd, z); break; + case WM_MOUSEWHEEL: stbwingraph__mousewheel(&e, STBWGE_mousewheel, wparam, lparam,0,wnd, z); break; + + case WM_ACTIVATE: + allow_default = FALSE; + if (LOWORD(wparam)==WA_INACTIVE ) { + wglMakeCurrent(z->dc, NULL); + e.type = STBWGE_deactivate; + z->active = FALSE; + } else { + wglMakeCurrent(z->dc, z->rc); + e.type = STBWGE_activate; + z->active = TRUE; + } + e.handle = wnd; + z->func(z->data, &e); + return 0; + + case WM_SIZE: { + RECT rect; + allow_default = FALSE; + GetClientRect(wnd, &rect); + e.type = STBWGE_size; + e.width = rect.right; + e.height = rect.bottom; + e.handle = wnd; + z->func(z->data, &e); + return 0; + } + + default: + return DefWindowProc (wnd, msg, wparam, lparam); + } + + if (e.type != STBWGE__none) { + int n; + e.handle = wnd; + n = z->func(z->data, &e); + if (n == STBWINGRAPH_winproc_exit) { + PostQuitMessage(0); + n = 0; + } + if (n == STBWINGRAPH_winproc_update) { + stbwingraph_force_update = TRUE; + return 1; + } + if (n != STBWINGRAPH_unprocessed) + return n; + } + return DefWindowProc (wnd, msg, wparam, lparam); +} + +int stbwingraph_DefineClass(HINSTANCE hInstance, char *iconname) +{ + WNDCLASSEX wndclass; + + stbwingraph_app = hInstance; + + wndclass.cbSize = sizeof(wndclass); + wndclass.style = CS_OWNDC; + wndclass.lpfnWndProc = (WNDPROC) stbwingraph_WinProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon(hInstance, iconname); + wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); + wndclass.hbrBackground = GetStockObject(NULL_BRUSH); + wndclass.lpszMenuName = "zwingraph"; + wndclass.lpszClassName = "zwingraph"; + wndclass.hIconSm = NULL; + + if (!RegisterClassEx(&wndclass)) + return FALSE; + return TRUE; +} + +void stbwingraph_ShowWindow(void *window) +{ + stbwingraph_event e = { STBWGE_create_postshow }; + stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA); + ShowWindow(window, SW_SHOWNORMAL); + InvalidateRect(window, NULL, TRUE); + UpdateWindow(window); + e.handle = window; + z->func(z->data, &e); +} + +void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, + int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil) +{ + HWND win; + DWORD dwstyle; + stbwingraph__window *z = (stbwingraph__window *) malloc(sizeof(*z)); + + if (z == NULL) return NULL; + memset(z, 0, sizeof(*z)); + z->color = 24; + z->depth = 24; + z->alpha = dest_alpha; + z->stencil = stencil; + z->func = func; + z->data = data; + z->mx = -(1 << 30); + z->my = 0; + + if (primary) { + if (stbwingraph_request_windowed) + fullscreen = FALSE; + else if (stbwingraph_request_fullscreen) + fullscreen = TRUE; + } + + if (fullscreen) { + #ifdef STB_SIMPLE + stbwingraph_ChangeResolution(width, height, 32, 1); + #else + if (!stbwingraph_ChangeResolution(width, height, 32, 0)) + return NULL; + #endif + dwstyle = WS_POPUP | WS_CLIPSIBLINGS; + } else { + RECT rect; + dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + if (resizeable) + dwstyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; + rect.top = 0; + rect.left = 0; + rect.right = width; + rect.bottom = height; + AdjustWindowRect(&rect, dwstyle, FALSE); + width = rect.right - rect.left; + height = rect.bottom - rect.top; + } + + win = CreateWindow("zwingraph", text ? text : "sample", dwstyle, + CW_USEDEFAULT,0, width, height, + NULL, NULL, stbwingraph_app, z); + + if (win == NULL) return win; + + if (primary) { + if (stbwingraph_primary_window) + stbwingraph_DestroyWindow(stbwingraph_primary_window); + stbwingraph_primary_window = win; + } + + { + stbwingraph_event e = { STBWGE_create }; + stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); + z->window = win; + e.did_share_lists = z->did_share_lists; + e.handle = win; + if (z->func(z->data, &e) != STBWINGRAPH_do_not_show) + stbwingraph_ShowWindow(win); + } + + return win; +} + +void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height) +{ + int fullscreen = 0; + #ifndef _DEBUG + if (width == 640 && height == 480) fullscreen = 1; + if (width == 800 && height == 600) fullscreen = 1; + if (width == 1024 && height == 768) fullscreen = 1; + if (width == 1280 && height == 1024) fullscreen = 1; + if (width == 1600 && height == 1200) fullscreen = 1; + //@TODO: widescreen widths + #endif + return stbwingraph_CreateWindow(1, func, NULL, NULL, width, height, fullscreen, 1, 0, 0); +} + +void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh) +{ + if (fullscreen == -1) { + #ifdef _DEBUG + fullscreen = 0; + #else + fullscreen = 1; + #endif + } + + if (fullscreen) { + if (fw) ww = fw; + if (fh) wh = fh; + } + return stbwingraph_CreateWindow(1, func, NULL, NULL, ww, wh, fullscreen, 1, 0, 0); +} + +void stbwingraph_DestroyWindow(void *window) +{ + stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA); + DestroyWindow(window); + free(z); + if (stbwingraph_primary_window == window) + stbwingraph_primary_window = NULL; +} + +void stbwingraph_ShowCursor(void *window, int visible) +{ + int hide; + stbwingraph__window *win; + if (!window) + window = stbwingraph_primary_window; + win = (stbwingraph__window *) GetWindowLong((HWND) window, GWL_USERDATA); + hide = !visible; + if (hide != win->hide_mouse) { + win->hide_mouse = hide; + if (!hide) + ShowCursor(TRUE); + else if (win->in_client) + ShowCursor(FALSE); + } +} + +float stbwingraph_GetTimestep(float minimum_time) +{ + float elapsedTime; + double thisTime; + static double lastTime = -1; + + if (lastTime == -1) + lastTime = timeGetTime() / 1000.0 - minimum_time; + + for(;;) { + thisTime = timeGetTime() / 1000.0; + elapsedTime = (float) (thisTime - lastTime); + if (elapsedTime >= minimum_time) { + lastTime = thisTime; + return elapsedTime; + } + #if 1 + Sleep(2); + #endif + } +} + +void stbwingraph_SetGLWindow(void *win) +{ + stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); + if (z) + wglMakeCurrent(z->dc, z->rc); +} + +void stbwingraph_MakeFonts(void *window, int font_base) +{ + wglUseFontBitmaps(GetDC(window ? window : stbwingraph_primary_window), 0, 256, font_base); +} + +// returns 1 if WM_QUIT, 0 if 'func' returned 0 +int stbwingraph_MainLoop(stbwingraph_update func, float mintime) +{ + int needs_drawing = FALSE; + MSG msg; + + int is_animating = TRUE; + if (mintime <= 0) mintime = 0.01f; + + for(;;) { + int n; + + is_animating = TRUE; + // wait for a message if: (a) we're animating and there's already a message + // or (b) we're not animating + if (!is_animating || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + stbwingraph_force_update = FALSE; + if (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + return 1; // WM_QUIT + } + + // only force a draw for certain messages... + // if I don't do this, we peg at 50% for some reason... must + // be a bug somewhere, because we peg at 100% when rendering... + // very weird... looks like NVIDIA is pumping some messages + // through our pipeline? well, ok, I guess if we can get + // non-user-generated messages we have to do this + if (!stbwingraph_force_update) { + switch (msg.message) { + case WM_MOUSEMOVE: + case WM_NCMOUSEMOVE: + break; + case WM_CHAR: + case WM_KEYDOWN: + case WM_KEYUP: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_TIMER: + case WM_SIZE: + case WM_ACTIVATE: + needs_drawing = TRUE; + break; + } + } else + needs_drawing = TRUE; + } + + // if another message, process that first + // @TODO: i don't think this is working, because I can't key ahead + // in the SVT demo app + if (PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE)) + continue; + + // and now call update + if (needs_drawing || is_animating) { + int real=1, in_client=1; + if (stbwingraph_primary_window) { + stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(stbwingraph_primary_window, GWL_USERDATA); + if (z && !z->active) { + real = 0; + } + if (z) + in_client = z->in_client; + } + + if (stbwingraph_primary_window) + stbwingraph_SetGLWindow(stbwingraph_primary_window); + n = func(stbwingraph_GetTimestep(mintime), real, in_client); + if (n == STBWINGRAPH_update_exit) + return 0; // update_quit + + is_animating = (n != STBWINGRAPH_update_pause); + + needs_drawing = FALSE; + } + } +} + +void stbwingraph_SwapBuffers(void *win) +{ + stbwingraph__window *z; + if (win == NULL) win = stbwingraph_primary_window; + z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); + if (z && z->dc) + SwapBuffers(z->dc); +} +#endif + +#ifdef STB_WINMAIN +void stbwingraph_main(void); + +char *stb_wingraph_commandline; + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + { + char buffer[1024]; + // add spaces to either side of the string + buffer[0] = ' '; + strcpy(buffer+1, lpCmdLine); + strcat(buffer, " "); + if (strstr(buffer, " -reset ")) { + ChangeDisplaySettings(NULL, 0); + exit(0); + } + if (strstr(buffer, " -window ") || strstr(buffer, " -windowed ")) + stbwingraph_request_windowed = TRUE; + else if (strstr(buffer, " -full ") || strstr(buffer, " -fullscreen ")) + stbwingraph_request_fullscreen = TRUE; + } + stb_wingraph_commandline = lpCmdLine; + + stbwingraph_DefineClass(hInstance, "appicon"); + stbwingraph_main(); + + return 0; +} +#endif + +#undef STB_EXTERN +#ifdef STB_WINGRAPH_DISABLE_DEFINE_AT_END +#undef STB_DEFINE +#endif + +#endif // INCLUDE_STB_WINGRAPH_H diff --git a/tests/pngsuite/16bit/basi0g16.png b/tests/pngsuite/16bit/basi0g16.png new file mode 100644 index 0000000..a9f2816 Binary files /dev/null and b/tests/pngsuite/16bit/basi0g16.png differ diff --git a/tests/pngsuite/16bit/basi2c16.png b/tests/pngsuite/16bit/basi2c16.png new file mode 100644 index 0000000..cd7e50f Binary files /dev/null and b/tests/pngsuite/16bit/basi2c16.png differ diff --git a/tests/pngsuite/16bit/basi4a16.png b/tests/pngsuite/16bit/basi4a16.png new file mode 100644 index 0000000..51192e7 Binary files /dev/null and b/tests/pngsuite/16bit/basi4a16.png differ diff --git a/tests/pngsuite/16bit/basi6a16.png b/tests/pngsuite/16bit/basi6a16.png new file mode 100644 index 0000000..4181533 Binary files /dev/null and b/tests/pngsuite/16bit/basi6a16.png differ diff --git a/tests/pngsuite/16bit/basn0g16.png b/tests/pngsuite/16bit/basn0g16.png new file mode 100644 index 0000000..e7c82f7 Binary files /dev/null and b/tests/pngsuite/16bit/basn0g16.png differ diff --git a/tests/pngsuite/16bit/basn2c16.png b/tests/pngsuite/16bit/basn2c16.png new file mode 100644 index 0000000..50c1cb9 Binary files /dev/null and b/tests/pngsuite/16bit/basn2c16.png differ diff --git a/tests/pngsuite/16bit/basn4a16.png b/tests/pngsuite/16bit/basn4a16.png new file mode 100644 index 0000000..8243644 Binary files /dev/null and b/tests/pngsuite/16bit/basn4a16.png differ diff --git a/tests/pngsuite/16bit/basn6a16.png b/tests/pngsuite/16bit/basn6a16.png new file mode 100644 index 0000000..984a995 Binary files /dev/null and b/tests/pngsuite/16bit/basn6a16.png differ diff --git a/tests/pngsuite/16bit/bgai4a16.png b/tests/pngsuite/16bit/bgai4a16.png new file mode 100644 index 0000000..51192e7 Binary files /dev/null and b/tests/pngsuite/16bit/bgai4a16.png differ diff --git a/tests/pngsuite/16bit/bgan6a16.png b/tests/pngsuite/16bit/bgan6a16.png new file mode 100644 index 0000000..984a995 Binary files /dev/null and b/tests/pngsuite/16bit/bgan6a16.png differ diff --git a/tests/pngsuite/16bit/bggn4a16.png b/tests/pngsuite/16bit/bggn4a16.png new file mode 100644 index 0000000..13fd85b Binary files /dev/null and b/tests/pngsuite/16bit/bggn4a16.png differ diff --git a/tests/pngsuite/16bit/bgyn6a16.png b/tests/pngsuite/16bit/bgyn6a16.png new file mode 100644 index 0000000..ae3e9be Binary files /dev/null and b/tests/pngsuite/16bit/bgyn6a16.png differ diff --git a/tests/pngsuite/16bit/oi1n0g16.png b/tests/pngsuite/16bit/oi1n0g16.png new file mode 100644 index 0000000..e7c82f7 Binary files /dev/null and b/tests/pngsuite/16bit/oi1n0g16.png differ diff --git a/tests/pngsuite/16bit/oi1n2c16.png b/tests/pngsuite/16bit/oi1n2c16.png new file mode 100644 index 0000000..50c1cb9 Binary files /dev/null and b/tests/pngsuite/16bit/oi1n2c16.png differ diff --git a/tests/pngsuite/16bit/oi2n0g16.png b/tests/pngsuite/16bit/oi2n0g16.png new file mode 100644 index 0000000..14d64c5 Binary files /dev/null and b/tests/pngsuite/16bit/oi2n0g16.png differ diff --git a/tests/pngsuite/16bit/oi2n2c16.png b/tests/pngsuite/16bit/oi2n2c16.png new file mode 100644 index 0000000..4c2e3e3 Binary files /dev/null and b/tests/pngsuite/16bit/oi2n2c16.png differ diff --git a/tests/pngsuite/16bit/oi4n0g16.png b/tests/pngsuite/16bit/oi4n0g16.png new file mode 100644 index 0000000..69e73ed Binary files /dev/null and b/tests/pngsuite/16bit/oi4n0g16.png differ diff --git a/tests/pngsuite/16bit/oi4n2c16.png b/tests/pngsuite/16bit/oi4n2c16.png new file mode 100644 index 0000000..93691e3 Binary files /dev/null and b/tests/pngsuite/16bit/oi4n2c16.png differ diff --git a/tests/pngsuite/16bit/oi9n0g16.png b/tests/pngsuite/16bit/oi9n0g16.png new file mode 100644 index 0000000..9248413 Binary files /dev/null and b/tests/pngsuite/16bit/oi9n0g16.png differ diff --git a/tests/pngsuite/16bit/oi9n2c16.png b/tests/pngsuite/16bit/oi9n2c16.png new file mode 100644 index 0000000..f0512e4 Binary files /dev/null and b/tests/pngsuite/16bit/oi9n2c16.png differ diff --git a/tests/pngsuite/16bit/tbbn2c16.png b/tests/pngsuite/16bit/tbbn2c16.png new file mode 100644 index 0000000..dd3168e Binary files /dev/null and b/tests/pngsuite/16bit/tbbn2c16.png differ diff --git a/tests/pngsuite/16bit/tbgn2c16.png b/tests/pngsuite/16bit/tbgn2c16.png new file mode 100644 index 0000000..85cec39 Binary files /dev/null and b/tests/pngsuite/16bit/tbgn2c16.png differ diff --git a/tests/pngsuite/16bit/tbwn0g16.png b/tests/pngsuite/16bit/tbwn0g16.png new file mode 100644 index 0000000..99bdeed Binary files /dev/null and b/tests/pngsuite/16bit/tbwn0g16.png differ diff --git a/tests/pngsuite/PngSuite.LICENSE b/tests/pngsuite/PngSuite.LICENSE new file mode 100644 index 0000000..8d4d1d0 --- /dev/null +++ b/tests/pngsuite/PngSuite.LICENSE @@ -0,0 +1,9 @@ +PngSuite +-------- + +Permission to use, copy, modify and distribute these images for any +purpose and without fee is hereby granted. + + +(c) Willem van Schaik, 1996, 2011 + diff --git a/tests/pngsuite/corrupt/xc1n0g08.png b/tests/pngsuite/corrupt/xc1n0g08.png new file mode 100644 index 0000000..9404227 Binary files /dev/null and b/tests/pngsuite/corrupt/xc1n0g08.png differ diff --git a/tests/pngsuite/corrupt/xc9n2c08.png b/tests/pngsuite/corrupt/xc9n2c08.png new file mode 100644 index 0000000..b11c2a7 Binary files /dev/null and b/tests/pngsuite/corrupt/xc9n2c08.png differ diff --git a/tests/pngsuite/corrupt/xcrn0g04.png b/tests/pngsuite/corrupt/xcrn0g04.png new file mode 100644 index 0000000..48abba1 Binary files /dev/null and b/tests/pngsuite/corrupt/xcrn0g04.png differ diff --git a/tests/pngsuite/corrupt/xcsn0g01.png b/tests/pngsuite/corrupt/xcsn0g01.png new file mode 100644 index 0000000..9863a26 Binary files /dev/null and b/tests/pngsuite/corrupt/xcsn0g01.png differ diff --git a/tests/pngsuite/corrupt/xd0n2c08.png b/tests/pngsuite/corrupt/xd0n2c08.png new file mode 100644 index 0000000..2f00161 Binary files /dev/null and b/tests/pngsuite/corrupt/xd0n2c08.png differ diff --git a/tests/pngsuite/corrupt/xd3n2c08.png b/tests/pngsuite/corrupt/xd3n2c08.png new file mode 100644 index 0000000..9e4a3ff Binary files /dev/null and b/tests/pngsuite/corrupt/xd3n2c08.png differ diff --git a/tests/pngsuite/corrupt/xd9n2c08.png b/tests/pngsuite/corrupt/xd9n2c08.png new file mode 100644 index 0000000..2c3b91a Binary files /dev/null and b/tests/pngsuite/corrupt/xd9n2c08.png differ diff --git a/tests/pngsuite/corrupt/xdtn0g01.png b/tests/pngsuite/corrupt/xdtn0g01.png new file mode 100644 index 0000000..1a81abe Binary files /dev/null and b/tests/pngsuite/corrupt/xdtn0g01.png differ diff --git a/tests/pngsuite/corrupt/xhdn0g08.png b/tests/pngsuite/corrupt/xhdn0g08.png new file mode 100644 index 0000000..fcb8737 Binary files /dev/null and b/tests/pngsuite/corrupt/xhdn0g08.png differ diff --git a/tests/pngsuite/corrupt/xlfn0g04.png b/tests/pngsuite/corrupt/xlfn0g04.png new file mode 100644 index 0000000..d9ec53e Binary files /dev/null and b/tests/pngsuite/corrupt/xlfn0g04.png differ diff --git a/tests/pngsuite/corrupt/xs1n0g01.png b/tests/pngsuite/corrupt/xs1n0g01.png new file mode 100644 index 0000000..1817c51 Binary files /dev/null and b/tests/pngsuite/corrupt/xs1n0g01.png differ diff --git a/tests/pngsuite/corrupt/xs2n0g01.png b/tests/pngsuite/corrupt/xs2n0g01.png new file mode 100644 index 0000000..b8147f2 Binary files /dev/null and b/tests/pngsuite/corrupt/xs2n0g01.png differ diff --git a/tests/pngsuite/corrupt/xs4n0g01.png b/tests/pngsuite/corrupt/xs4n0g01.png new file mode 100644 index 0000000..45237a1 Binary files /dev/null and b/tests/pngsuite/corrupt/xs4n0g01.png differ diff --git a/tests/pngsuite/corrupt/xs7n0g01.png b/tests/pngsuite/corrupt/xs7n0g01.png new file mode 100644 index 0000000..3f307f1 Binary files /dev/null and b/tests/pngsuite/corrupt/xs7n0g01.png differ diff --git a/tests/pngsuite/primary/basi0g01.png b/tests/pngsuite/primary/basi0g01.png new file mode 100644 index 0000000..556fa72 Binary files /dev/null and b/tests/pngsuite/primary/basi0g01.png differ diff --git a/tests/pngsuite/primary/basi0g02.png b/tests/pngsuite/primary/basi0g02.png new file mode 100644 index 0000000..ce09821 Binary files /dev/null and b/tests/pngsuite/primary/basi0g02.png differ diff --git a/tests/pngsuite/primary/basi0g04.png b/tests/pngsuite/primary/basi0g04.png new file mode 100644 index 0000000..3853273 Binary files /dev/null and b/tests/pngsuite/primary/basi0g04.png differ diff --git a/tests/pngsuite/primary/basi0g08.png b/tests/pngsuite/primary/basi0g08.png new file mode 100644 index 0000000..faed8be Binary files /dev/null and b/tests/pngsuite/primary/basi0g08.png differ diff --git a/tests/pngsuite/primary/basi2c08.png b/tests/pngsuite/primary/basi2c08.png new file mode 100644 index 0000000..2aab44d Binary files /dev/null and b/tests/pngsuite/primary/basi2c08.png differ diff --git a/tests/pngsuite/primary/basi3p01.png b/tests/pngsuite/primary/basi3p01.png new file mode 100644 index 0000000..00a7cea Binary files /dev/null and b/tests/pngsuite/primary/basi3p01.png differ diff --git a/tests/pngsuite/primary/basi3p02.png b/tests/pngsuite/primary/basi3p02.png new file mode 100644 index 0000000..bb16b44 Binary files /dev/null and b/tests/pngsuite/primary/basi3p02.png differ diff --git a/tests/pngsuite/primary/basi3p04.png b/tests/pngsuite/primary/basi3p04.png new file mode 100644 index 0000000..b4e888e Binary files /dev/null and b/tests/pngsuite/primary/basi3p04.png differ diff --git a/tests/pngsuite/primary/basi3p08.png b/tests/pngsuite/primary/basi3p08.png new file mode 100644 index 0000000..50a6d1c Binary files /dev/null and b/tests/pngsuite/primary/basi3p08.png differ diff --git a/tests/pngsuite/primary/basi4a08.png b/tests/pngsuite/primary/basi4a08.png new file mode 100644 index 0000000..398132b Binary files /dev/null and b/tests/pngsuite/primary/basi4a08.png differ diff --git a/tests/pngsuite/primary/basi6a08.png b/tests/pngsuite/primary/basi6a08.png new file mode 100644 index 0000000..aecb32e Binary files /dev/null and b/tests/pngsuite/primary/basi6a08.png differ diff --git a/tests/pngsuite/primary/basn0g01.png b/tests/pngsuite/primary/basn0g01.png new file mode 100644 index 0000000..1d72242 Binary files /dev/null and b/tests/pngsuite/primary/basn0g01.png differ diff --git a/tests/pngsuite/primary/basn0g02.png b/tests/pngsuite/primary/basn0g02.png new file mode 100644 index 0000000..5083324 Binary files /dev/null and b/tests/pngsuite/primary/basn0g02.png differ diff --git a/tests/pngsuite/primary/basn0g04.png b/tests/pngsuite/primary/basn0g04.png new file mode 100644 index 0000000..0bf3687 Binary files /dev/null and b/tests/pngsuite/primary/basn0g04.png differ diff --git a/tests/pngsuite/primary/basn0g08.png b/tests/pngsuite/primary/basn0g08.png new file mode 100644 index 0000000..23c8237 Binary files /dev/null and b/tests/pngsuite/primary/basn0g08.png differ diff --git a/tests/pngsuite/primary/basn2c08.png b/tests/pngsuite/primary/basn2c08.png new file mode 100644 index 0000000..db5ad15 Binary files /dev/null and b/tests/pngsuite/primary/basn2c08.png differ diff --git a/tests/pngsuite/primary/basn3p01.png b/tests/pngsuite/primary/basn3p01.png new file mode 100644 index 0000000..b145c2b Binary files /dev/null and b/tests/pngsuite/primary/basn3p01.png differ diff --git a/tests/pngsuite/primary/basn3p02.png b/tests/pngsuite/primary/basn3p02.png new file mode 100644 index 0000000..8985b3d Binary files /dev/null and b/tests/pngsuite/primary/basn3p02.png differ diff --git a/tests/pngsuite/primary/basn3p04.png b/tests/pngsuite/primary/basn3p04.png new file mode 100644 index 0000000..0fbf9e8 Binary files /dev/null and b/tests/pngsuite/primary/basn3p04.png differ diff --git a/tests/pngsuite/primary/basn3p08.png b/tests/pngsuite/primary/basn3p08.png new file mode 100644 index 0000000..0ddad07 Binary files /dev/null and b/tests/pngsuite/primary/basn3p08.png differ diff --git a/tests/pngsuite/primary/basn4a08.png b/tests/pngsuite/primary/basn4a08.png new file mode 100644 index 0000000..3e13052 Binary files /dev/null and b/tests/pngsuite/primary/basn4a08.png differ diff --git a/tests/pngsuite/primary/basn6a08.png b/tests/pngsuite/primary/basn6a08.png new file mode 100644 index 0000000..e608738 Binary files /dev/null and b/tests/pngsuite/primary/basn6a08.png differ diff --git a/tests/pngsuite/primary/bgai4a08.png b/tests/pngsuite/primary/bgai4a08.png new file mode 100644 index 0000000..398132b Binary files /dev/null and b/tests/pngsuite/primary/bgai4a08.png differ diff --git a/tests/pngsuite/primary/bgan6a08.png b/tests/pngsuite/primary/bgan6a08.png new file mode 100644 index 0000000..e608738 Binary files /dev/null and b/tests/pngsuite/primary/bgan6a08.png differ diff --git a/tests/pngsuite/primary/bgbn4a08.png b/tests/pngsuite/primary/bgbn4a08.png new file mode 100644 index 0000000..7cbefc3 Binary files /dev/null and b/tests/pngsuite/primary/bgbn4a08.png differ diff --git a/tests/pngsuite/primary/bgwn6a08.png b/tests/pngsuite/primary/bgwn6a08.png new file mode 100644 index 0000000..a67ff20 Binary files /dev/null and b/tests/pngsuite/primary/bgwn6a08.png differ diff --git a/tests/pngsuite/primary/s01i3p01.png b/tests/pngsuite/primary/s01i3p01.png new file mode 100644 index 0000000..6c0fad1 Binary files /dev/null and b/tests/pngsuite/primary/s01i3p01.png differ diff --git a/tests/pngsuite/primary/s01n3p01.png b/tests/pngsuite/primary/s01n3p01.png new file mode 100644 index 0000000..cb2c8c7 Binary files /dev/null and b/tests/pngsuite/primary/s01n3p01.png differ diff --git a/tests/pngsuite/primary/s02i3p01.png b/tests/pngsuite/primary/s02i3p01.png new file mode 100644 index 0000000..2defaed Binary files /dev/null and b/tests/pngsuite/primary/s02i3p01.png differ diff --git a/tests/pngsuite/primary/s02n3p01.png b/tests/pngsuite/primary/s02n3p01.png new file mode 100644 index 0000000..2b1b669 Binary files /dev/null and b/tests/pngsuite/primary/s02n3p01.png differ diff --git a/tests/pngsuite/primary/s03i3p01.png b/tests/pngsuite/primary/s03i3p01.png new file mode 100644 index 0000000..c23fdc4 Binary files /dev/null and b/tests/pngsuite/primary/s03i3p01.png differ diff --git a/tests/pngsuite/primary/s03n3p01.png b/tests/pngsuite/primary/s03n3p01.png new file mode 100644 index 0000000..6d96ee4 Binary files /dev/null and b/tests/pngsuite/primary/s03n3p01.png differ diff --git a/tests/pngsuite/primary/s04i3p01.png b/tests/pngsuite/primary/s04i3p01.png new file mode 100644 index 0000000..0e710c2 Binary files /dev/null and b/tests/pngsuite/primary/s04i3p01.png differ diff --git a/tests/pngsuite/primary/s04n3p01.png b/tests/pngsuite/primary/s04n3p01.png new file mode 100644 index 0000000..956396c Binary files /dev/null and b/tests/pngsuite/primary/s04n3p01.png differ diff --git a/tests/pngsuite/primary/s05i3p02.png b/tests/pngsuite/primary/s05i3p02.png new file mode 100644 index 0000000..d14cbd3 Binary files /dev/null and b/tests/pngsuite/primary/s05i3p02.png differ diff --git a/tests/pngsuite/primary/s05n3p02.png b/tests/pngsuite/primary/s05n3p02.png new file mode 100644 index 0000000..bf940f0 Binary files /dev/null and b/tests/pngsuite/primary/s05n3p02.png differ diff --git a/tests/pngsuite/primary/s06i3p02.png b/tests/pngsuite/primary/s06i3p02.png new file mode 100644 index 0000000..456ada3 Binary files /dev/null and b/tests/pngsuite/primary/s06i3p02.png differ diff --git a/tests/pngsuite/primary/s06n3p02.png b/tests/pngsuite/primary/s06n3p02.png new file mode 100644 index 0000000..501064d Binary files /dev/null and b/tests/pngsuite/primary/s06n3p02.png differ diff --git a/tests/pngsuite/primary/s07i3p02.png b/tests/pngsuite/primary/s07i3p02.png new file mode 100644 index 0000000..44b66ba Binary files /dev/null and b/tests/pngsuite/primary/s07i3p02.png differ diff --git a/tests/pngsuite/primary/s07n3p02.png b/tests/pngsuite/primary/s07n3p02.png new file mode 100644 index 0000000..6a58259 Binary files /dev/null and b/tests/pngsuite/primary/s07n3p02.png differ diff --git a/tests/pngsuite/primary/s08i3p02.png b/tests/pngsuite/primary/s08i3p02.png new file mode 100644 index 0000000..acf74f3 Binary files /dev/null and b/tests/pngsuite/primary/s08i3p02.png differ diff --git a/tests/pngsuite/primary/s08n3p02.png b/tests/pngsuite/primary/s08n3p02.png new file mode 100644 index 0000000..b7094e1 Binary files /dev/null and b/tests/pngsuite/primary/s08n3p02.png differ diff --git a/tests/pngsuite/primary/s09i3p02.png b/tests/pngsuite/primary/s09i3p02.png new file mode 100644 index 0000000..0bfae8e Binary files /dev/null and b/tests/pngsuite/primary/s09i3p02.png differ diff --git a/tests/pngsuite/primary/s09n3p02.png b/tests/pngsuite/primary/s09n3p02.png new file mode 100644 index 0000000..711ab82 Binary files /dev/null and b/tests/pngsuite/primary/s09n3p02.png differ diff --git a/tests/pngsuite/primary/s32i3p04.png b/tests/pngsuite/primary/s32i3p04.png new file mode 100644 index 0000000..0841910 Binary files /dev/null and b/tests/pngsuite/primary/s32i3p04.png differ diff --git a/tests/pngsuite/primary/s32n3p04.png b/tests/pngsuite/primary/s32n3p04.png new file mode 100644 index 0000000..fa58e3e Binary files /dev/null and b/tests/pngsuite/primary/s32n3p04.png differ diff --git a/tests/pngsuite/primary/s33i3p04.png b/tests/pngsuite/primary/s33i3p04.png new file mode 100644 index 0000000..ab0dc14 Binary files /dev/null and b/tests/pngsuite/primary/s33i3p04.png differ diff --git a/tests/pngsuite/primary/s33n3p04.png b/tests/pngsuite/primary/s33n3p04.png new file mode 100644 index 0000000..764f1a3 Binary files /dev/null and b/tests/pngsuite/primary/s33n3p04.png differ diff --git a/tests/pngsuite/primary/s34i3p04.png b/tests/pngsuite/primary/s34i3p04.png new file mode 100644 index 0000000..bd99039 Binary files /dev/null and b/tests/pngsuite/primary/s34i3p04.png differ diff --git a/tests/pngsuite/primary/s34n3p04.png b/tests/pngsuite/primary/s34n3p04.png new file mode 100644 index 0000000..9cbc68b Binary files /dev/null and b/tests/pngsuite/primary/s34n3p04.png differ diff --git a/tests/pngsuite/primary/s35i3p04.png b/tests/pngsuite/primary/s35i3p04.png new file mode 100644 index 0000000..e2a5e0a Binary files /dev/null and b/tests/pngsuite/primary/s35i3p04.png differ diff --git a/tests/pngsuite/primary/s35n3p04.png b/tests/pngsuite/primary/s35n3p04.png new file mode 100644 index 0000000..90b892e Binary files /dev/null and b/tests/pngsuite/primary/s35n3p04.png differ diff --git a/tests/pngsuite/primary/s36i3p04.png b/tests/pngsuite/primary/s36i3p04.png new file mode 100644 index 0000000..eb61b6f Binary files /dev/null and b/tests/pngsuite/primary/s36i3p04.png differ diff --git a/tests/pngsuite/primary/s36n3p04.png b/tests/pngsuite/primary/s36n3p04.png new file mode 100644 index 0000000..b38d179 Binary files /dev/null and b/tests/pngsuite/primary/s36n3p04.png differ diff --git a/tests/pngsuite/primary/s37i3p04.png b/tests/pngsuite/primary/s37i3p04.png new file mode 100644 index 0000000..6e2b1e9 Binary files /dev/null and b/tests/pngsuite/primary/s37i3p04.png differ diff --git a/tests/pngsuite/primary/s37n3p04.png b/tests/pngsuite/primary/s37n3p04.png new file mode 100644 index 0000000..4d3054d Binary files /dev/null and b/tests/pngsuite/primary/s37n3p04.png differ diff --git a/tests/pngsuite/primary/s38i3p04.png b/tests/pngsuite/primary/s38i3p04.png new file mode 100644 index 0000000..a0a8a14 Binary files /dev/null and b/tests/pngsuite/primary/s38i3p04.png differ diff --git a/tests/pngsuite/primary/s38n3p04.png b/tests/pngsuite/primary/s38n3p04.png new file mode 100644 index 0000000..1233ed0 Binary files /dev/null and b/tests/pngsuite/primary/s38n3p04.png differ diff --git a/tests/pngsuite/primary/s39i3p04.png b/tests/pngsuite/primary/s39i3p04.png new file mode 100644 index 0000000..04fee93 Binary files /dev/null and b/tests/pngsuite/primary/s39i3p04.png differ diff --git a/tests/pngsuite/primary/s39n3p04.png b/tests/pngsuite/primary/s39n3p04.png new file mode 100644 index 0000000..c750100 Binary files /dev/null and b/tests/pngsuite/primary/s39n3p04.png differ diff --git a/tests/pngsuite/primary/s40i3p04.png b/tests/pngsuite/primary/s40i3p04.png new file mode 100644 index 0000000..68f358b Binary files /dev/null and b/tests/pngsuite/primary/s40i3p04.png differ diff --git a/tests/pngsuite/primary/s40n3p04.png b/tests/pngsuite/primary/s40n3p04.png new file mode 100644 index 0000000..864b6b9 Binary files /dev/null and b/tests/pngsuite/primary/s40n3p04.png differ diff --git a/tests/pngsuite/primary/tbbn0g04.png b/tests/pngsuite/primary/tbbn0g04.png new file mode 100644 index 0000000..39a7050 Binary files /dev/null and b/tests/pngsuite/primary/tbbn0g04.png differ diff --git a/tests/pngsuite/primary/tbbn3p08.png b/tests/pngsuite/primary/tbbn3p08.png new file mode 100644 index 0000000..0ede357 Binary files /dev/null and b/tests/pngsuite/primary/tbbn3p08.png differ diff --git a/tests/pngsuite/primary/tbgn3p08.png b/tests/pngsuite/primary/tbgn3p08.png new file mode 100644 index 0000000..8cf2e6f Binary files /dev/null and b/tests/pngsuite/primary/tbgn3p08.png differ diff --git a/tests/pngsuite/primary/tbrn2c08.png b/tests/pngsuite/primary/tbrn2c08.png new file mode 100644 index 0000000..5cca0d6 Binary files /dev/null and b/tests/pngsuite/primary/tbrn2c08.png differ diff --git a/tests/pngsuite/primary/tbwn3p08.png b/tests/pngsuite/primary/tbwn3p08.png new file mode 100644 index 0000000..eacab7a Binary files /dev/null and b/tests/pngsuite/primary/tbwn3p08.png differ diff --git a/tests/pngsuite/primary/tbyn3p08.png b/tests/pngsuite/primary/tbyn3p08.png new file mode 100644 index 0000000..656db09 Binary files /dev/null and b/tests/pngsuite/primary/tbyn3p08.png differ diff --git a/tests/pngsuite/primary/tm3n3p02.png b/tests/pngsuite/primary/tm3n3p02.png new file mode 100644 index 0000000..fb3ef1d Binary files /dev/null and b/tests/pngsuite/primary/tm3n3p02.png differ diff --git a/tests/pngsuite/primary/tp0n0g08.png b/tests/pngsuite/primary/tp0n0g08.png new file mode 100644 index 0000000..333465f Binary files /dev/null and b/tests/pngsuite/primary/tp0n0g08.png differ diff --git a/tests/pngsuite/primary/tp0n2c08.png b/tests/pngsuite/primary/tp0n2c08.png new file mode 100644 index 0000000..fc6e42c Binary files /dev/null and b/tests/pngsuite/primary/tp0n2c08.png differ diff --git a/tests/pngsuite/primary/tp0n3p08.png b/tests/pngsuite/primary/tp0n3p08.png new file mode 100644 index 0000000..69a69e5 Binary files /dev/null and b/tests/pngsuite/primary/tp0n3p08.png differ diff --git a/tests/pngsuite/primary/tp1n3p08.png b/tests/pngsuite/primary/tp1n3p08.png new file mode 100644 index 0000000..a6c9f35 Binary files /dev/null and b/tests/pngsuite/primary/tp1n3p08.png differ diff --git a/tests/pngsuite/primary/z00n2c08.png b/tests/pngsuite/primary/z00n2c08.png new file mode 100644 index 0000000..7669eb8 Binary files /dev/null and b/tests/pngsuite/primary/z00n2c08.png differ diff --git a/tests/pngsuite/primary/z03n2c08.png b/tests/pngsuite/primary/z03n2c08.png new file mode 100644 index 0000000..bfb10de Binary files /dev/null and b/tests/pngsuite/primary/z03n2c08.png differ diff --git a/tests/pngsuite/primary/z06n2c08.png b/tests/pngsuite/primary/z06n2c08.png new file mode 100644 index 0000000..b90ebc1 Binary files /dev/null and b/tests/pngsuite/primary/z06n2c08.png differ diff --git a/tests/pngsuite/primary/z09n2c08.png b/tests/pngsuite/primary/z09n2c08.png new file mode 100644 index 0000000..5f191a7 Binary files /dev/null and b/tests/pngsuite/primary/z09n2c08.png differ diff --git a/tests/pngsuite/primary_check/basi0g01.png b/tests/pngsuite/primary_check/basi0g01.png new file mode 100644 index 0000000..96ed62d Binary files /dev/null and b/tests/pngsuite/primary_check/basi0g01.png differ diff --git a/tests/pngsuite/primary_check/basi0g02.png b/tests/pngsuite/primary_check/basi0g02.png new file mode 100644 index 0000000..bb53098 Binary files /dev/null and b/tests/pngsuite/primary_check/basi0g02.png differ diff --git a/tests/pngsuite/primary_check/basi0g04.png b/tests/pngsuite/primary_check/basi0g04.png new file mode 100644 index 0000000..2efd487 Binary files /dev/null and b/tests/pngsuite/primary_check/basi0g04.png differ diff --git a/tests/pngsuite/primary_check/basi0g08.png b/tests/pngsuite/primary_check/basi0g08.png new file mode 100644 index 0000000..2395213 Binary files /dev/null and b/tests/pngsuite/primary_check/basi0g08.png differ diff --git a/tests/pngsuite/primary_check/basi2c08.png b/tests/pngsuite/primary_check/basi2c08.png new file mode 100644 index 0000000..64ef3f8 Binary files /dev/null and b/tests/pngsuite/primary_check/basi2c08.png differ diff --git a/tests/pngsuite/primary_check/basi3p01.png b/tests/pngsuite/primary_check/basi3p01.png new file mode 100644 index 0000000..a8599e9 Binary files /dev/null and b/tests/pngsuite/primary_check/basi3p01.png differ diff --git a/tests/pngsuite/primary_check/basi3p02.png b/tests/pngsuite/primary_check/basi3p02.png new file mode 100644 index 0000000..c911ea9 Binary files /dev/null and b/tests/pngsuite/primary_check/basi3p02.png differ diff --git a/tests/pngsuite/primary_check/basi3p04.png b/tests/pngsuite/primary_check/basi3p04.png new file mode 100644 index 0000000..750ef69 Binary files /dev/null and b/tests/pngsuite/primary_check/basi3p04.png differ diff --git a/tests/pngsuite/primary_check/basi3p08.png b/tests/pngsuite/primary_check/basi3p08.png new file mode 100644 index 0000000..39272c3 Binary files /dev/null and b/tests/pngsuite/primary_check/basi3p08.png differ diff --git a/tests/pngsuite/primary_check/basi4a08.png b/tests/pngsuite/primary_check/basi4a08.png new file mode 100644 index 0000000..1b7b3a5 Binary files /dev/null and b/tests/pngsuite/primary_check/basi4a08.png differ diff --git a/tests/pngsuite/primary_check/basi6a08.png b/tests/pngsuite/primary_check/basi6a08.png new file mode 100644 index 0000000..c12484f Binary files /dev/null and b/tests/pngsuite/primary_check/basi6a08.png differ diff --git a/tests/pngsuite/primary_check/basn0g01.png b/tests/pngsuite/primary_check/basn0g01.png new file mode 100644 index 0000000..20f6404 Binary files /dev/null and b/tests/pngsuite/primary_check/basn0g01.png differ diff --git a/tests/pngsuite/primary_check/basn0g02.png b/tests/pngsuite/primary_check/basn0g02.png new file mode 100644 index 0000000..c4fae00 Binary files /dev/null and b/tests/pngsuite/primary_check/basn0g02.png differ diff --git a/tests/pngsuite/primary_check/basn0g04.png b/tests/pngsuite/primary_check/basn0g04.png new file mode 100644 index 0000000..166e7db Binary files /dev/null and b/tests/pngsuite/primary_check/basn0g04.png differ diff --git a/tests/pngsuite/primary_check/basn0g08.png b/tests/pngsuite/primary_check/basn0g08.png new file mode 100644 index 0000000..192c792 Binary files /dev/null and b/tests/pngsuite/primary_check/basn0g08.png differ diff --git a/tests/pngsuite/primary_check/basn2c08.png b/tests/pngsuite/primary_check/basn2c08.png new file mode 100644 index 0000000..d774b80 Binary files /dev/null and b/tests/pngsuite/primary_check/basn2c08.png differ diff --git a/tests/pngsuite/primary_check/basn3p01.png b/tests/pngsuite/primary_check/basn3p01.png new file mode 100644 index 0000000..77c580b Binary files /dev/null and b/tests/pngsuite/primary_check/basn3p01.png differ diff --git a/tests/pngsuite/primary_check/basn3p02.png b/tests/pngsuite/primary_check/basn3p02.png new file mode 100644 index 0000000..8427124 Binary files /dev/null and b/tests/pngsuite/primary_check/basn3p02.png differ diff --git a/tests/pngsuite/primary_check/basn3p04.png b/tests/pngsuite/primary_check/basn3p04.png new file mode 100644 index 0000000..f08c6e9 Binary files /dev/null and b/tests/pngsuite/primary_check/basn3p04.png differ diff --git a/tests/pngsuite/primary_check/basn3p08.png b/tests/pngsuite/primary_check/basn3p08.png new file mode 100644 index 0000000..0fa8195 Binary files /dev/null and b/tests/pngsuite/primary_check/basn3p08.png differ diff --git a/tests/pngsuite/primary_check/basn4a08.png b/tests/pngsuite/primary_check/basn4a08.png new file mode 100644 index 0000000..d4e0a72 Binary files /dev/null and b/tests/pngsuite/primary_check/basn4a08.png differ diff --git a/tests/pngsuite/primary_check/basn6a08.png b/tests/pngsuite/primary_check/basn6a08.png new file mode 100644 index 0000000..1f54e56 Binary files /dev/null and b/tests/pngsuite/primary_check/basn6a08.png differ diff --git a/tests/pngsuite/primary_check/bgai4a08.png b/tests/pngsuite/primary_check/bgai4a08.png new file mode 100644 index 0000000..23ec6ae Binary files /dev/null and b/tests/pngsuite/primary_check/bgai4a08.png differ diff --git a/tests/pngsuite/primary_check/bgan6a08.png b/tests/pngsuite/primary_check/bgan6a08.png new file mode 100644 index 0000000..6cb76f2 Binary files /dev/null and b/tests/pngsuite/primary_check/bgan6a08.png differ diff --git a/tests/pngsuite/primary_check/bgbn4a08.png b/tests/pngsuite/primary_check/bgbn4a08.png new file mode 100644 index 0000000..1086ccc Binary files /dev/null and b/tests/pngsuite/primary_check/bgbn4a08.png differ diff --git a/tests/pngsuite/primary_check/bgwn6a08.png b/tests/pngsuite/primary_check/bgwn6a08.png new file mode 100644 index 0000000..03a0a30 Binary files /dev/null and b/tests/pngsuite/primary_check/bgwn6a08.png differ diff --git a/tests/pngsuite/primary_check/s01i3p01.png b/tests/pngsuite/primary_check/s01i3p01.png new file mode 100644 index 0000000..45f8c61 Binary files /dev/null and b/tests/pngsuite/primary_check/s01i3p01.png differ diff --git a/tests/pngsuite/primary_check/s01n3p01.png b/tests/pngsuite/primary_check/s01n3p01.png new file mode 100644 index 0000000..a79ac1b Binary files /dev/null and b/tests/pngsuite/primary_check/s01n3p01.png differ diff --git a/tests/pngsuite/primary_check/s02i3p01.png b/tests/pngsuite/primary_check/s02i3p01.png new file mode 100644 index 0000000..d84f406 Binary files /dev/null and b/tests/pngsuite/primary_check/s02i3p01.png differ diff --git a/tests/pngsuite/primary_check/s02n3p01.png b/tests/pngsuite/primary_check/s02n3p01.png new file mode 100644 index 0000000..3b813c4 Binary files /dev/null and b/tests/pngsuite/primary_check/s02n3p01.png differ diff --git a/tests/pngsuite/primary_check/s03i3p01.png b/tests/pngsuite/primary_check/s03i3p01.png new file mode 100644 index 0000000..51367f7 Binary files /dev/null and b/tests/pngsuite/primary_check/s03i3p01.png differ diff --git a/tests/pngsuite/primary_check/s03n3p01.png b/tests/pngsuite/primary_check/s03n3p01.png new file mode 100644 index 0000000..7c44b73 Binary files /dev/null and b/tests/pngsuite/primary_check/s03n3p01.png differ diff --git a/tests/pngsuite/primary_check/s04i3p01.png b/tests/pngsuite/primary_check/s04i3p01.png new file mode 100644 index 0000000..ae326c1 Binary files /dev/null and b/tests/pngsuite/primary_check/s04i3p01.png differ diff --git a/tests/pngsuite/primary_check/s04n3p01.png b/tests/pngsuite/primary_check/s04n3p01.png new file mode 100644 index 0000000..55c63df Binary files /dev/null and b/tests/pngsuite/primary_check/s04n3p01.png differ diff --git a/tests/pngsuite/primary_check/s05i3p02.png b/tests/pngsuite/primary_check/s05i3p02.png new file mode 100644 index 0000000..fd41d1d Binary files /dev/null and b/tests/pngsuite/primary_check/s05i3p02.png differ diff --git a/tests/pngsuite/primary_check/s05n3p02.png b/tests/pngsuite/primary_check/s05n3p02.png new file mode 100644 index 0000000..d6ab572 Binary files /dev/null and b/tests/pngsuite/primary_check/s05n3p02.png differ diff --git a/tests/pngsuite/primary_check/s06i3p02.png b/tests/pngsuite/primary_check/s06i3p02.png new file mode 100644 index 0000000..73a7b0c Binary files /dev/null and b/tests/pngsuite/primary_check/s06i3p02.png differ diff --git a/tests/pngsuite/primary_check/s06n3p02.png b/tests/pngsuite/primary_check/s06n3p02.png new file mode 100644 index 0000000..e85eac8 Binary files /dev/null and b/tests/pngsuite/primary_check/s06n3p02.png differ diff --git a/tests/pngsuite/primary_check/s07i3p02.png b/tests/pngsuite/primary_check/s07i3p02.png new file mode 100644 index 0000000..08f6180 Binary files /dev/null and b/tests/pngsuite/primary_check/s07i3p02.png differ diff --git a/tests/pngsuite/primary_check/s07n3p02.png b/tests/pngsuite/primary_check/s07n3p02.png new file mode 100644 index 0000000..029bc29 Binary files /dev/null and b/tests/pngsuite/primary_check/s07n3p02.png differ diff --git a/tests/pngsuite/primary_check/s08i3p02.png b/tests/pngsuite/primary_check/s08i3p02.png new file mode 100644 index 0000000..23d16c7 Binary files /dev/null and b/tests/pngsuite/primary_check/s08i3p02.png differ diff --git a/tests/pngsuite/primary_check/s08n3p02.png b/tests/pngsuite/primary_check/s08n3p02.png new file mode 100644 index 0000000..4a46016 Binary files /dev/null and b/tests/pngsuite/primary_check/s08n3p02.png differ diff --git a/tests/pngsuite/primary_check/s09i3p02.png b/tests/pngsuite/primary_check/s09i3p02.png new file mode 100644 index 0000000..ea14f9b Binary files /dev/null and b/tests/pngsuite/primary_check/s09i3p02.png differ diff --git a/tests/pngsuite/primary_check/s09n3p02.png b/tests/pngsuite/primary_check/s09n3p02.png new file mode 100644 index 0000000..7a82253 Binary files /dev/null and b/tests/pngsuite/primary_check/s09n3p02.png differ diff --git a/tests/pngsuite/primary_check/s32i3p04.png b/tests/pngsuite/primary_check/s32i3p04.png new file mode 100644 index 0000000..db4bef7 Binary files /dev/null and b/tests/pngsuite/primary_check/s32i3p04.png differ diff --git a/tests/pngsuite/primary_check/s32n3p04.png b/tests/pngsuite/primary_check/s32n3p04.png new file mode 100644 index 0000000..c250971 Binary files /dev/null and b/tests/pngsuite/primary_check/s32n3p04.png differ diff --git a/tests/pngsuite/primary_check/s33i3p04.png b/tests/pngsuite/primary_check/s33i3p04.png new file mode 100644 index 0000000..0faaa74 Binary files /dev/null and b/tests/pngsuite/primary_check/s33i3p04.png differ diff --git a/tests/pngsuite/primary_check/s33n3p04.png b/tests/pngsuite/primary_check/s33n3p04.png new file mode 100644 index 0000000..599171c Binary files /dev/null and b/tests/pngsuite/primary_check/s33n3p04.png differ diff --git a/tests/pngsuite/primary_check/s34i3p04.png b/tests/pngsuite/primary_check/s34i3p04.png new file mode 100644 index 0000000..ca0e5eb Binary files /dev/null and b/tests/pngsuite/primary_check/s34i3p04.png differ diff --git a/tests/pngsuite/primary_check/s34n3p04.png b/tests/pngsuite/primary_check/s34n3p04.png new file mode 100644 index 0000000..b175f59 Binary files /dev/null and b/tests/pngsuite/primary_check/s34n3p04.png differ diff --git a/tests/pngsuite/primary_check/s35i3p04.png b/tests/pngsuite/primary_check/s35i3p04.png new file mode 100644 index 0000000..ccb1b8a Binary files /dev/null and b/tests/pngsuite/primary_check/s35i3p04.png differ diff --git a/tests/pngsuite/primary_check/s35n3p04.png b/tests/pngsuite/primary_check/s35n3p04.png new file mode 100644 index 0000000..2c7219f Binary files /dev/null and b/tests/pngsuite/primary_check/s35n3p04.png differ diff --git a/tests/pngsuite/primary_check/s36i3p04.png b/tests/pngsuite/primary_check/s36i3p04.png new file mode 100644 index 0000000..d61491f Binary files /dev/null and b/tests/pngsuite/primary_check/s36i3p04.png differ diff --git a/tests/pngsuite/primary_check/s36n3p04.png b/tests/pngsuite/primary_check/s36n3p04.png new file mode 100644 index 0000000..1f50479 Binary files /dev/null and b/tests/pngsuite/primary_check/s36n3p04.png differ diff --git a/tests/pngsuite/primary_check/s37i3p04.png b/tests/pngsuite/primary_check/s37i3p04.png new file mode 100644 index 0000000..2906fa3 Binary files /dev/null and b/tests/pngsuite/primary_check/s37i3p04.png differ diff --git a/tests/pngsuite/primary_check/s37n3p04.png b/tests/pngsuite/primary_check/s37n3p04.png new file mode 100644 index 0000000..8931b85 Binary files /dev/null and b/tests/pngsuite/primary_check/s37n3p04.png differ diff --git a/tests/pngsuite/primary_check/s38i3p04.png b/tests/pngsuite/primary_check/s38i3p04.png new file mode 100644 index 0000000..becf5a1 Binary files /dev/null and b/tests/pngsuite/primary_check/s38i3p04.png differ diff --git a/tests/pngsuite/primary_check/s38n3p04.png b/tests/pngsuite/primary_check/s38n3p04.png new file mode 100644 index 0000000..43f8c98 Binary files /dev/null and b/tests/pngsuite/primary_check/s38n3p04.png differ diff --git a/tests/pngsuite/primary_check/s39i3p04.png b/tests/pngsuite/primary_check/s39i3p04.png new file mode 100644 index 0000000..b045ad5 Binary files /dev/null and b/tests/pngsuite/primary_check/s39i3p04.png differ diff --git a/tests/pngsuite/primary_check/s39n3p04.png b/tests/pngsuite/primary_check/s39n3p04.png new file mode 100644 index 0000000..d37d66d Binary files /dev/null and b/tests/pngsuite/primary_check/s39n3p04.png differ diff --git a/tests/pngsuite/primary_check/s40i3p04.png b/tests/pngsuite/primary_check/s40i3p04.png new file mode 100644 index 0000000..dd2f7a1 Binary files /dev/null and b/tests/pngsuite/primary_check/s40i3p04.png differ diff --git a/tests/pngsuite/primary_check/s40n3p04.png b/tests/pngsuite/primary_check/s40n3p04.png new file mode 100644 index 0000000..6f8596c Binary files /dev/null and b/tests/pngsuite/primary_check/s40n3p04.png differ diff --git a/tests/pngsuite/primary_check/tbbn0g04.png b/tests/pngsuite/primary_check/tbbn0g04.png new file mode 100644 index 0000000..8d9f7d5 Binary files /dev/null and b/tests/pngsuite/primary_check/tbbn0g04.png differ diff --git a/tests/pngsuite/primary_check/tbbn3p08.png b/tests/pngsuite/primary_check/tbbn3p08.png new file mode 100644 index 0000000..706e6c4 Binary files /dev/null and b/tests/pngsuite/primary_check/tbbn3p08.png differ diff --git a/tests/pngsuite/primary_check/tbgn3p08.png b/tests/pngsuite/primary_check/tbgn3p08.png new file mode 100644 index 0000000..fa5cdbc Binary files /dev/null and b/tests/pngsuite/primary_check/tbgn3p08.png differ diff --git a/tests/pngsuite/primary_check/tbrn2c08.png b/tests/pngsuite/primary_check/tbrn2c08.png new file mode 100644 index 0000000..bbe748f Binary files /dev/null and b/tests/pngsuite/primary_check/tbrn2c08.png differ diff --git a/tests/pngsuite/primary_check/tbwn3p08.png b/tests/pngsuite/primary_check/tbwn3p08.png new file mode 100644 index 0000000..9ecd404 Binary files /dev/null and b/tests/pngsuite/primary_check/tbwn3p08.png differ diff --git a/tests/pngsuite/primary_check/tbyn3p08.png b/tests/pngsuite/primary_check/tbyn3p08.png new file mode 100644 index 0000000..4fbdb36 Binary files /dev/null and b/tests/pngsuite/primary_check/tbyn3p08.png differ diff --git a/tests/pngsuite/primary_check/tm3n3p02.png b/tests/pngsuite/primary_check/tm3n3p02.png new file mode 100644 index 0000000..babdebe Binary files /dev/null and b/tests/pngsuite/primary_check/tm3n3p02.png differ diff --git a/tests/pngsuite/primary_check/tp0n0g08.png b/tests/pngsuite/primary_check/tp0n0g08.png new file mode 100644 index 0000000..96dd89c Binary files /dev/null and b/tests/pngsuite/primary_check/tp0n0g08.png differ diff --git a/tests/pngsuite/primary_check/tp0n2c08.png b/tests/pngsuite/primary_check/tp0n2c08.png new file mode 100644 index 0000000..364e97e Binary files /dev/null and b/tests/pngsuite/primary_check/tp0n2c08.png differ diff --git a/tests/pngsuite/primary_check/tp0n3p08.png b/tests/pngsuite/primary_check/tp0n3p08.png new file mode 100644 index 0000000..e5a29d6 Binary files /dev/null and b/tests/pngsuite/primary_check/tp0n3p08.png differ diff --git a/tests/pngsuite/primary_check/tp1n3p08.png b/tests/pngsuite/primary_check/tp1n3p08.png new file mode 100644 index 0000000..9ecd404 Binary files /dev/null and b/tests/pngsuite/primary_check/tp1n3p08.png differ diff --git a/tests/pngsuite/primary_check/z00n2c08.png b/tests/pngsuite/primary_check/z00n2c08.png new file mode 100644 index 0000000..ecaa0d8 Binary files /dev/null and b/tests/pngsuite/primary_check/z00n2c08.png differ diff --git a/tests/pngsuite/primary_check/z03n2c08.png b/tests/pngsuite/primary_check/z03n2c08.png new file mode 100644 index 0000000..ecaa0d8 Binary files /dev/null and b/tests/pngsuite/primary_check/z03n2c08.png differ diff --git a/tests/pngsuite/primary_check/z06n2c08.png b/tests/pngsuite/primary_check/z06n2c08.png new file mode 100644 index 0000000..ecaa0d8 Binary files /dev/null and b/tests/pngsuite/primary_check/z06n2c08.png differ diff --git a/tests/pngsuite/primary_check/z09n2c08.png b/tests/pngsuite/primary_check/z09n2c08.png new file mode 100644 index 0000000..d869f99 Binary files /dev/null and b/tests/pngsuite/primary_check/z09n2c08.png differ diff --git a/tests/pngsuite/unused/ccwn2c08.png b/tests/pngsuite/unused/ccwn2c08.png new file mode 100644 index 0000000..47c2481 Binary files /dev/null and b/tests/pngsuite/unused/ccwn2c08.png differ diff --git a/tests/pngsuite/unused/ccwn3p08.png b/tests/pngsuite/unused/ccwn3p08.png new file mode 100644 index 0000000..8bb2c10 Binary files /dev/null and b/tests/pngsuite/unused/ccwn3p08.png differ diff --git a/tests/pngsuite/unused/cdfn2c08.png b/tests/pngsuite/unused/cdfn2c08.png new file mode 100644 index 0000000..559e526 Binary files /dev/null and b/tests/pngsuite/unused/cdfn2c08.png differ diff --git a/tests/pngsuite/unused/cdhn2c08.png b/tests/pngsuite/unused/cdhn2c08.png new file mode 100644 index 0000000..3e07e8e Binary files /dev/null and b/tests/pngsuite/unused/cdhn2c08.png differ diff --git a/tests/pngsuite/unused/cdsn2c08.png b/tests/pngsuite/unused/cdsn2c08.png new file mode 100644 index 0000000..076c32c Binary files /dev/null and b/tests/pngsuite/unused/cdsn2c08.png differ diff --git a/tests/pngsuite/unused/cdun2c08.png b/tests/pngsuite/unused/cdun2c08.png new file mode 100644 index 0000000..846033b Binary files /dev/null and b/tests/pngsuite/unused/cdun2c08.png differ diff --git a/tests/pngsuite/unused/ch1n3p04.png b/tests/pngsuite/unused/ch1n3p04.png new file mode 100644 index 0000000..17cd12d Binary files /dev/null and b/tests/pngsuite/unused/ch1n3p04.png differ diff --git a/tests/pngsuite/unused/ch2n3p08.png b/tests/pngsuite/unused/ch2n3p08.png new file mode 100644 index 0000000..25c1798 Binary files /dev/null and b/tests/pngsuite/unused/ch2n3p08.png differ diff --git a/tests/pngsuite/unused/cm0n0g04.png b/tests/pngsuite/unused/cm0n0g04.png new file mode 100644 index 0000000..9fba5db Binary files /dev/null and b/tests/pngsuite/unused/cm0n0g04.png differ diff --git a/tests/pngsuite/unused/cm7n0g04.png b/tests/pngsuite/unused/cm7n0g04.png new file mode 100644 index 0000000..f7dc46e Binary files /dev/null and b/tests/pngsuite/unused/cm7n0g04.png differ diff --git a/tests/pngsuite/unused/cm9n0g04.png b/tests/pngsuite/unused/cm9n0g04.png new file mode 100644 index 0000000..dd70911 Binary files /dev/null and b/tests/pngsuite/unused/cm9n0g04.png differ diff --git a/tests/pngsuite/unused/cs3n2c16.png b/tests/pngsuite/unused/cs3n2c16.png new file mode 100644 index 0000000..bf5fd20 Binary files /dev/null and b/tests/pngsuite/unused/cs3n2c16.png differ diff --git a/tests/pngsuite/unused/cs3n3p08.png b/tests/pngsuite/unused/cs3n3p08.png new file mode 100644 index 0000000..f4a6623 Binary files /dev/null and b/tests/pngsuite/unused/cs3n3p08.png differ diff --git a/tests/pngsuite/unused/cs5n2c08.png b/tests/pngsuite/unused/cs5n2c08.png new file mode 100644 index 0000000..40f947c Binary files /dev/null and b/tests/pngsuite/unused/cs5n2c08.png differ diff --git a/tests/pngsuite/unused/cs5n3p08.png b/tests/pngsuite/unused/cs5n3p08.png new file mode 100644 index 0000000..dfd6e6e Binary files /dev/null and b/tests/pngsuite/unused/cs5n3p08.png differ diff --git a/tests/pngsuite/unused/cs8n2c08.png b/tests/pngsuite/unused/cs8n2c08.png new file mode 100644 index 0000000..8e01d32 Binary files /dev/null and b/tests/pngsuite/unused/cs8n2c08.png differ diff --git a/tests/pngsuite/unused/cs8n3p08.png b/tests/pngsuite/unused/cs8n3p08.png new file mode 100644 index 0000000..a44066e Binary files /dev/null and b/tests/pngsuite/unused/cs8n3p08.png differ diff --git a/tests/pngsuite/unused/ct0n0g04.png b/tests/pngsuite/unused/ct0n0g04.png new file mode 100644 index 0000000..40d1e06 Binary files /dev/null and b/tests/pngsuite/unused/ct0n0g04.png differ diff --git a/tests/pngsuite/unused/ct1n0g04.png b/tests/pngsuite/unused/ct1n0g04.png new file mode 100644 index 0000000..3ba110a Binary files /dev/null and b/tests/pngsuite/unused/ct1n0g04.png differ diff --git a/tests/pngsuite/unused/cten0g04.png b/tests/pngsuite/unused/cten0g04.png new file mode 100644 index 0000000..a6a56fa Binary files /dev/null and b/tests/pngsuite/unused/cten0g04.png differ diff --git a/tests/pngsuite/unused/ctfn0g04.png b/tests/pngsuite/unused/ctfn0g04.png new file mode 100644 index 0000000..353873e Binary files /dev/null and b/tests/pngsuite/unused/ctfn0g04.png differ diff --git a/tests/pngsuite/unused/ctgn0g04.png b/tests/pngsuite/unused/ctgn0g04.png new file mode 100644 index 0000000..453f2b0 Binary files /dev/null and b/tests/pngsuite/unused/ctgn0g04.png differ diff --git a/tests/pngsuite/unused/cthn0g04.png b/tests/pngsuite/unused/cthn0g04.png new file mode 100644 index 0000000..8fce253 Binary files /dev/null and b/tests/pngsuite/unused/cthn0g04.png differ diff --git a/tests/pngsuite/unused/ctjn0g04.png b/tests/pngsuite/unused/ctjn0g04.png new file mode 100644 index 0000000..a77b8d2 Binary files /dev/null and b/tests/pngsuite/unused/ctjn0g04.png differ diff --git a/tests/pngsuite/unused/ctzn0g04.png b/tests/pngsuite/unused/ctzn0g04.png new file mode 100644 index 0000000..b4401c9 Binary files /dev/null and b/tests/pngsuite/unused/ctzn0g04.png differ diff --git a/tests/pngsuite/unused/f00n0g08.png b/tests/pngsuite/unused/f00n0g08.png new file mode 100644 index 0000000..45a0075 Binary files /dev/null and b/tests/pngsuite/unused/f00n0g08.png differ diff --git a/tests/pngsuite/unused/f00n2c08.png b/tests/pngsuite/unused/f00n2c08.png new file mode 100644 index 0000000..d6a1fff Binary files /dev/null and b/tests/pngsuite/unused/f00n2c08.png differ diff --git a/tests/pngsuite/unused/f01n0g08.png b/tests/pngsuite/unused/f01n0g08.png new file mode 100644 index 0000000..4a1107b Binary files /dev/null and b/tests/pngsuite/unused/f01n0g08.png differ diff --git a/tests/pngsuite/unused/f01n2c08.png b/tests/pngsuite/unused/f01n2c08.png new file mode 100644 index 0000000..26fee95 Binary files /dev/null and b/tests/pngsuite/unused/f01n2c08.png differ diff --git a/tests/pngsuite/unused/f02n0g08.png b/tests/pngsuite/unused/f02n0g08.png new file mode 100644 index 0000000..bfe410c Binary files /dev/null and b/tests/pngsuite/unused/f02n0g08.png differ diff --git a/tests/pngsuite/unused/f02n2c08.png b/tests/pngsuite/unused/f02n2c08.png new file mode 100644 index 0000000..e590f12 Binary files /dev/null and b/tests/pngsuite/unused/f02n2c08.png differ diff --git a/tests/pngsuite/unused/f03n0g08.png b/tests/pngsuite/unused/f03n0g08.png new file mode 100644 index 0000000..ed01e29 Binary files /dev/null and b/tests/pngsuite/unused/f03n0g08.png differ diff --git a/tests/pngsuite/unused/f03n2c08.png b/tests/pngsuite/unused/f03n2c08.png new file mode 100644 index 0000000..7581150 Binary files /dev/null and b/tests/pngsuite/unused/f03n2c08.png differ diff --git a/tests/pngsuite/unused/f04n0g08.png b/tests/pngsuite/unused/f04n0g08.png new file mode 100644 index 0000000..663fdae Binary files /dev/null and b/tests/pngsuite/unused/f04n0g08.png differ diff --git a/tests/pngsuite/unused/f04n2c08.png b/tests/pngsuite/unused/f04n2c08.png new file mode 100644 index 0000000..3c8b511 Binary files /dev/null and b/tests/pngsuite/unused/f04n2c08.png differ diff --git a/tests/pngsuite/unused/f99n0g04.png b/tests/pngsuite/unused/f99n0g04.png new file mode 100644 index 0000000..0b521c1 Binary files /dev/null and b/tests/pngsuite/unused/f99n0g04.png differ diff --git a/tests/pngsuite/unused/g03n0g16.png b/tests/pngsuite/unused/g03n0g16.png new file mode 100644 index 0000000..41083ca Binary files /dev/null and b/tests/pngsuite/unused/g03n0g16.png differ diff --git a/tests/pngsuite/unused/g03n2c08.png b/tests/pngsuite/unused/g03n2c08.png new file mode 100644 index 0000000..a9354db Binary files /dev/null and b/tests/pngsuite/unused/g03n2c08.png differ diff --git a/tests/pngsuite/unused/g03n3p04.png b/tests/pngsuite/unused/g03n3p04.png new file mode 100644 index 0000000..60396c9 Binary files /dev/null and b/tests/pngsuite/unused/g03n3p04.png differ diff --git a/tests/pngsuite/unused/g04n0g16.png b/tests/pngsuite/unused/g04n0g16.png new file mode 100644 index 0000000..32395b7 Binary files /dev/null and b/tests/pngsuite/unused/g04n0g16.png differ diff --git a/tests/pngsuite/unused/g04n2c08.png b/tests/pngsuite/unused/g04n2c08.png new file mode 100644 index 0000000..a652b0c Binary files /dev/null and b/tests/pngsuite/unused/g04n2c08.png differ diff --git a/tests/pngsuite/unused/g04n3p04.png b/tests/pngsuite/unused/g04n3p04.png new file mode 100644 index 0000000..5661cc3 Binary files /dev/null and b/tests/pngsuite/unused/g04n3p04.png differ diff --git a/tests/pngsuite/unused/g05n0g16.png b/tests/pngsuite/unused/g05n0g16.png new file mode 100644 index 0000000..70b37f0 Binary files /dev/null and b/tests/pngsuite/unused/g05n0g16.png differ diff --git a/tests/pngsuite/unused/g05n2c08.png b/tests/pngsuite/unused/g05n2c08.png new file mode 100644 index 0000000..932c136 Binary files /dev/null and b/tests/pngsuite/unused/g05n2c08.png differ diff --git a/tests/pngsuite/unused/g05n3p04.png b/tests/pngsuite/unused/g05n3p04.png new file mode 100644 index 0000000..9619930 Binary files /dev/null and b/tests/pngsuite/unused/g05n3p04.png differ diff --git a/tests/pngsuite/unused/g07n0g16.png b/tests/pngsuite/unused/g07n0g16.png new file mode 100644 index 0000000..d6a47c2 Binary files /dev/null and b/tests/pngsuite/unused/g07n0g16.png differ diff --git a/tests/pngsuite/unused/g07n2c08.png b/tests/pngsuite/unused/g07n2c08.png new file mode 100644 index 0000000..5973464 Binary files /dev/null and b/tests/pngsuite/unused/g07n2c08.png differ diff --git a/tests/pngsuite/unused/g07n3p04.png b/tests/pngsuite/unused/g07n3p04.png new file mode 100644 index 0000000..c73fb61 Binary files /dev/null and b/tests/pngsuite/unused/g07n3p04.png differ diff --git a/tests/pngsuite/unused/g10n0g16.png b/tests/pngsuite/unused/g10n0g16.png new file mode 100644 index 0000000..85f2c95 Binary files /dev/null and b/tests/pngsuite/unused/g10n0g16.png differ diff --git a/tests/pngsuite/unused/g10n2c08.png b/tests/pngsuite/unused/g10n2c08.png new file mode 100644 index 0000000..b303997 Binary files /dev/null and b/tests/pngsuite/unused/g10n2c08.png differ diff --git a/tests/pngsuite/unused/g10n3p04.png b/tests/pngsuite/unused/g10n3p04.png new file mode 100644 index 0000000..1b6a6be Binary files /dev/null and b/tests/pngsuite/unused/g10n3p04.png differ diff --git a/tests/pngsuite/unused/g25n0g16.png b/tests/pngsuite/unused/g25n0g16.png new file mode 100644 index 0000000..a9f6787 Binary files /dev/null and b/tests/pngsuite/unused/g25n0g16.png differ diff --git a/tests/pngsuite/unused/g25n2c08.png b/tests/pngsuite/unused/g25n2c08.png new file mode 100644 index 0000000..03f505a Binary files /dev/null and b/tests/pngsuite/unused/g25n2c08.png differ diff --git a/tests/pngsuite/unused/g25n3p04.png b/tests/pngsuite/unused/g25n3p04.png new file mode 100644 index 0000000..4f943c6 Binary files /dev/null and b/tests/pngsuite/unused/g25n3p04.png differ diff --git a/tests/pngsuite/unused/pp0n2c16.png b/tests/pngsuite/unused/pp0n2c16.png new file mode 100644 index 0000000..8f2aad7 Binary files /dev/null and b/tests/pngsuite/unused/pp0n2c16.png differ diff --git a/tests/pngsuite/unused/pp0n6a08.png b/tests/pngsuite/unused/pp0n6a08.png new file mode 100644 index 0000000..4ed7a30 Binary files /dev/null and b/tests/pngsuite/unused/pp0n6a08.png differ diff --git a/tests/pngsuite/unused/ps1n0g08.png b/tests/pngsuite/unused/ps1n0g08.png new file mode 100644 index 0000000..99625fa Binary files /dev/null and b/tests/pngsuite/unused/ps1n0g08.png differ diff --git a/tests/pngsuite/unused/ps1n2c16.png b/tests/pngsuite/unused/ps1n2c16.png new file mode 100644 index 0000000..0c7a6b3 Binary files /dev/null and b/tests/pngsuite/unused/ps1n2c16.png differ diff --git a/tests/pngsuite/unused/ps2n0g08.png b/tests/pngsuite/unused/ps2n0g08.png new file mode 100644 index 0000000..90b2979 Binary files /dev/null and b/tests/pngsuite/unused/ps2n0g08.png differ diff --git a/tests/pngsuite/unused/ps2n2c16.png b/tests/pngsuite/unused/ps2n2c16.png new file mode 100644 index 0000000..a4a181e Binary files /dev/null and b/tests/pngsuite/unused/ps2n2c16.png differ diff --git a/tests/resize.dsp b/tests/resize.dsp index e670af2..0aa1bba 100644 --- a/tests/resize.dsp +++ b/tests/resize.dsp @@ -65,7 +65,8 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /WX /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/tests/stb.dsp b/tests/stb.dsp index a68755a..3d642a1 100644 --- a/tests/stb.dsp +++ b/tests/stb.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MT /W3 /GX /Z7 /O2 /Ob2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "MAIN_TEST" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /GX /Z7 /O2 /Ob2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "TT_TEST" /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -126,10 +126,18 @@ SOURCE=..\stb_perlin.h # End Source File # Begin Source File +SOURCE=..\stb_rect_pack.h +# End Source File +# Begin Source File + SOURCE=..\stb_textedit.h # End Source File # Begin Source File +SOURCE=..\stb_tilemap_editor.h +# End Source File +# Begin Source File + SOURCE=..\stb_truetype.h # End Source File # Begin Source File diff --git a/tests/stb_cpp.dsp b/tests/stb_cpp.dsp index f14aa82..8bf9975 100644 --- a/tests/stb_cpp.dsp +++ b/tests/stb_cpp.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -65,7 +65,8 @@ 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 /Zd /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /GX /Zd /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/tests/stretch_test.c b/tests/stretch_test.c index 2c097bd..8caf43f 100644 --- a/tests/stretch_test.c +++ b/tests/stretch_test.c @@ -1,3 +1,7 @@ +// check that stb_truetype compiles with no stb_rect_pack.h +#define STB_TRUETYPE_IMPLEMENTATION +#include "stb_truetype.h" + #include "stretchy_buffer.h" #include diff --git a/tests/stretch_test.dsp b/tests/stretch_test.dsp index f9af713..dd0442c 100644 --- a/tests/stretch_test.dsp +++ b/tests/stretch_test.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "TT_TEST" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -63,8 +63,9 @@ LINK32=link.exe # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug\stretch_test" # PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index 25ff374..2aa85b0 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -6,6 +6,7 @@ #define STB_IMAGE_IMPLEMENTATION #define STB_HERRINGBONE_WANG_TILE_IMEPLEMENTATIOn #define STB_IMAGE_RESIZE_IMPLEMENTATION +#define STB_RECT_PACK_IMPLEMENTATION #include "stb_herringbone_wang_tile.h" #include "stb_image.h" @@ -15,9 +16,9 @@ #include "stb_c_lexer.h" #include "stb_divide.h" #include "stb_image_resize.h" +#include "stb_rect_pack.h" - -#define STBTE_DRAW_RECT(x0,y0,x1,y1,color) 0 -#define STBTE_DRAW_TILE(x,y,id,highlight) 0 +#define STBTE_DRAW_RECT(x0,y0,x1,y1,color) 0 +#define STBTE_DRAW_TILE(x,y,id,highlight,data) 0 #define STB_TILEMAP_EDITOR_IMPLEMENTATION #include "stb_tilemap_editor.h" diff --git a/tests/test_cpp_compilation.cpp b/tests/test_cpp_compilation.cpp index 3f33d89..44262fb 100644 --- a/tests/test_cpp_compilation.cpp +++ b/tests/test_cpp_compilation.cpp @@ -1,4 +1,4 @@ -#define STB_TRUETYPE_IMPLEMENTATIOn +#define STB_TRUETYPE_IMPLEMENTATION #define STB_PERLIN_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_DXT_IMPLEMENATION @@ -6,17 +6,19 @@ #define STB_DIVIDE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define STB_HERRINGBONE_WANG_TILE_IMPLEMENTATION +#define STB_RECT_PACK_IMPLEMENTATION +#include "stb_image.h" +#include "stb_rect_pack.h" #include "stb_truetype.h" #include "stb_image_write.h" #include "stb_perlin.h" #include "stb_dxt.h" #include "stb_c_lexer.h" #include "stb_divide.h" -#include "stb_image.h" #include "stb_herringbone_wang_tile.h" -#define STBTE_DRAW_RECT(x0,y0,x1,y1,color) -#define STBTE_DRAW_TILE(x,y,id,highlight) +#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" diff --git a/tests/test_truetype.c b/tests/test_truetype.c index 4706f22..c151533 100644 --- a/tests/test_truetype.c +++ b/tests/test_truetype.c @@ -1,5 +1,7 @@ +#include "stb_rect_pack.h" #define STB_TRUETYPE_IMPLEMENTATION #include "stb_truetype.h" +#include "stb_image_write.h" #include @@ -17,16 +19,55 @@ void debug(void) stbtt_MakeGlyphBitmap(&font, output, 6, 9, 512, 5.172414E-03f, 5.172414E-03f, 54); } +#define BITMAP_W 256 +#define BITMAP_H 512 +unsigned char temp_bitmap[BITMAP_H][BITMAP_W]; +stbtt_bakedchar cdata[256*2]; // ASCII 32..126 is 95 glyphs +stbtt_packedchar pdata[256*2]; int main(int argc, char **argv) { stbtt_fontinfo font; unsigned char *bitmap; int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 34807), s = (argc > 2 ? atoi(argv[2]) : 32); - debug(); + //debug(); + // @TODO: why is minglui.ttc failing? fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/mingliu.ttc", "rb")); + stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits! + stbi_write_png("fonttest1.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0); + + { + stbtt_pack_context pc; + stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL); + stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 32, 95, pdata); + stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 0xa0, 0x100-0xa0, pdata); + stbtt_PackEnd(&pc); + stbi_write_png("fonttest2.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0); + } + + { + stbtt_pack_context pc; + stbtt_pack_range pr[2]; + stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL); + + pr[0].chardata_for_range = pdata; + pr[0].first_unicode_char_in_range = 32; + pr[0].num_chars_in_range = 95; + pr[0].font_size = 20.0f; + pr[1].chardata_for_range = pdata+256; + pr[1].first_unicode_char_in_range = 0xa0; + pr[1].num_chars_in_range = 0x100 - 0xa0; + pr[1].font_size = 20.0f; + + stbtt_PackSetOversampling(&pc, 2, 2); + stbtt_PackFontRanges(&pc, ttf_buffer, 0, pr, 2); + stbtt_PackEnd(&pc); + stbi_write_png("fonttest3.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0); + } + return 0; + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, (float)s), c, &w, &h, 0,0); diff --git a/tools/README.list b/tools/README.list index de628e8..c53b0db 100644 --- a/tools/README.list +++ b/tools/README.list @@ -3,6 +3,7 @@ stb_image.h | graphics | image loading/decoding from file/mem stb_truetype.h | graphics | parse, decode, and rasterize characters from truetype fonts stb_image_write.h | graphics | image writing to disk: PNG, TGA, BMP stb_image_resize.h | graphics | resize images larger/smaller with good quality +stb_rect_pack.h | graphics | simple 2D rectangle packer with decent quality stretchy_buffer.h | utility | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ stb_textedit.h | UI | guts of a text editor for games etc implementing them from scratch stb_dxt.h | 3D graphics | Fabian "ryg" Giesen's real-time DXT compressor diff --git a/tools/make_readme.dsp b/tools/make_readme.dsp index 1cc079a..e5969ae 100644 --- a/tools/make_readme.dsp +++ b/tools/make_readme.dsp @@ -64,7 +64,8 @@ LINK32=link.exe # PROP Intermediate_Dir "Debug\make_readme" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe