From 45fec171488b1bbf3f602d8ffd269a78e9eaa49c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 21 Jan 2015 23:38:29 +0100 Subject: [PATCH 01/23] stb_truetype: added STBTT_STATIC to make all implementation static Followed the structure used by stb_rectpack. Functions that had neither extern neither static got STBTT_DEF as well. --- stb_truetype.h | 184 +++++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 89 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 56ef47b..df5b75a 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -376,6 +376,12 @@ int main(int arg, char **argv) typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + #ifdef STBTT_STATIC + #define STBTT_DEF static + #else + #define STBTT_DEF extern + #endif + // #define your own STBTT_sort() to override this to avoid qsort #ifndef STBTT_sort #include @@ -445,7 +451,7 @@ typedef struct float xoff,yoff,xadvance; } stbtt_bakedchar; -extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake @@ -461,7 +467,7 @@ typedef struct float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; -extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *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 @@ -494,7 +500,7 @@ typedef struct 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); +STBTT_DEF 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 @@ -505,12 +511,12 @@ extern int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int // // Returns 0 on failure, 1 on success. -extern void stbtt_PackEnd (stbtt_pack_context *spc); +STBTT_DEF 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, +STBTT_DEF 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 @@ -533,13 +539,13 @@ typedef struct 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); +STBTT_DEF 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); +STBTT_DEF 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. // @@ -551,7 +557,7 @@ extern void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_ov // 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 +STBTT_DEF 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 @@ -577,7 +583,7 @@ struct stbtt_pack_context { // // -extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // Each .ttf/.ttc file may have more than one font. Each font has a sequential // index number starting from 0. Call this function to get the font offset for // a given index; it returns -1 if the index is out of range. A regular .ttf @@ -601,7 +607,7 @@ typedef struct stbtt_fontinfo int indexToLocFormat; // format needed to map from glyph index to glyph } stbtt_fontinfo; -extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); // Given an offset into the file that defines a font, this function builds // the necessary cached info for the rest of the system. You must allocate // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't @@ -613,7 +619,7 @@ extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int o // // CHARACTER TO GLYPH-INDEX CONVERSIOn -int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); // If you're going to perform multiple operations on the same character // and you want a speed-up, call this function with the character you're // going to process, then use glyph-based functions instead of the @@ -625,7 +631,7 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); // CHARACTER PROPERTIES // -extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); // computes a scale factor to produce a font whose "height" is 'pixels' tall. // Height is measured as the distance from the highest ascender to the lowest // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics @@ -633,12 +639,12 @@ extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels) // scale = pixels / (ascent - descent) // so if you prefer to measure height by the ascent only, use a similar calculation. -extern float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); // computes a scale factor to produce a font whose EM size is mapped to // 'pixels' tall. This is probably what traditional APIs compute, but // I'm not positive. -extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); // ascent is the coordinate above the baseline the font extends; descent // is the coordinate below the baseline the font extends (i.e. it is typically negative) // lineGap is the spacing between one row's descent and the next row's ascent... @@ -646,23 +652,23 @@ extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int * // these are expressed in unscaled coordinates, so you must multiply by // the scale factor for a given size -extern void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); // the bounding box around all possible characters -extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); // leftSideBearing is the offset from the current horizontal position to the left edge of the character // advanceWidth is the offset from the current horizontal position to the next horizontal position // these are expressed in unscaled coordinates -extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); // an additional amount to add to the 'advance' value between ch1 and ch2 -extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); // Gets the bounding box of the visible part of the glyph, in unscaled coordinates -extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); -extern int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); -extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); // as above, but takes one or more glyph indices for greater efficiency @@ -690,11 +696,11 @@ extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int * } stbtt_vertex; #endif -extern int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); // returns non-zero if nothing is drawn for this glyph -extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); -extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); // returns # of vertices and fills *vertices with the pointer to them // these are expressed in "unscaled" coordinates // @@ -705,7 +711,7 @@ extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbt // draws a quadratic bezier from previous endpoint to // its x,y, using cx,cy as the bezier control point. -extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); // frees the data allocated above ////////////////////////////////////////////////////////////////////////////// @@ -713,10 +719,10 @@ extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); // BITMAP RENDERING // -extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); // frees the bitmap allocated below -extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); // allocates a large-enough single-channel 8bpp bitmap and renders the // specified character/glyph at the specified scale into it, with // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). @@ -725,39 +731,39 @@ extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float // // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap -extern unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel // shift for the character -extern void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the // width and height and positioning info for it first. -extern void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel // shift for the character -extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // get the bbox of the bitmap centered around the glyph origin; so the // bitmap width is ix1-ix0, height is iy1-iy0, and location to place // the bitmap top left is (leftSideBearing*scale,iy0). // (Note that the bitmap uses y-increases-down, but the shape uses // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) -extern void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel // shift for the character // the following functions are equivalent to the above functions, but operate // on glyph indices instead of Unicode codepoints (for efficiency) -extern unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); -extern unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); -extern void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); -extern void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); -extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); -extern void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); // @TODO: don't expose this structure @@ -767,7 +773,7 @@ typedef struct unsigned char *pixels; } stbtt__bitmap; -extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata); +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata); ////////////////////////////////////////////////////////////////////////////// // @@ -791,7 +797,7 @@ extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stb // You have to have called stbtt_InitFont() first. -extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); // returns the offset (not index) of the font that matches, or -1 if none // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". // if you use any other flag, use a font name like "Arial"; this checks @@ -802,11 +808,11 @@ extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *nam #define STBTT_MACSTYLE_UNDERSCORE 4 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 -extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); // returns 1/0 whether the first string interpreted as utf8 is identical to // the second string interpreted as big-endian utf16... useful for strings from next func -extern const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); // returns the string (which may be big-endian double byte, e.g. for unicode) // and puts the length in bytes in *length. // @@ -905,10 +911,10 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #else - stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } + static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } + static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } #endif @@ -939,7 +945,7 @@ static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, return 0; } -int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) { // if it's just a font, there's only one valid index if (stbtt__isfont(font_collection)) @@ -958,7 +964,7 @@ int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) return -1; } -int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) { stbtt_uint8 *data = (stbtt_uint8 *) data2; stbtt_uint32 cmap, t; @@ -1015,7 +1021,7 @@ int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontsta return 1; } -int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) { stbtt_uint8 *data = info->data; stbtt_uint32 index_map = info->index_map; @@ -1107,7 +1113,7 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) return 0; } -int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) { return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); } @@ -1139,7 +1145,7 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) return g1==g2 ? -1 : g1; // if length is 0, return -1 } -int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { int g = stbtt__GetGlyfOffset(info, glyph_index); if (g < 0) return 0; @@ -1151,12 +1157,12 @@ int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int return 1; } -int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) { return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); } -int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) { stbtt_int16 numberOfContours; int g = stbtt__GetGlyfOffset(info, glyph_index); @@ -1181,7 +1187,7 @@ static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_ return num_vertices; } -int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { stbtt_int16 numberOfContours; stbtt_uint8 *endPtsOfContours; @@ -1407,7 +1413,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte return num_vertices; } -void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) { stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); if (glyph_index < numOfLongHorMetrics) { @@ -1419,7 +1425,7 @@ void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *ad } } -int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -1449,26 +1455,26 @@ int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph return 0; } -int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } -void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) { stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); } -void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) { if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); if (descent) *descent = ttSHORT(info->data+info->hhea + 6); if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); } -void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { *x0 = ttSHORT(info->data + info->head + 36); *y0 = ttSHORT(info->data + info->head + 38); @@ -1476,19 +1482,19 @@ void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *y1 = ttSHORT(info->data + info->head + 42); } -float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) { int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); return (float) height / fheight; } -float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) { int unitsPerEm = ttUSHORT(info->data + info->head + 18); return pixels / unitsPerEm; } -void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) { STBTT_free(v, info->userdata); } @@ -1498,7 +1504,7 @@ void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) // antialiasing software rasterizer // -void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { int x0,y0,x1,y1; if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { @@ -1516,17 +1522,17 @@ void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, floa } } -void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) { stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); } -void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); } -void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) { stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); } @@ -1807,7 +1813,7 @@ static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x } // returns number of contours -stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { stbtt__point *points=0; int num_points=0; @@ -1876,7 +1882,7 @@ error: return NULL; } -void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { float scale = scale_x > scale_y ? scale_y : scale_x; int winding_count, *winding_lengths; @@ -1888,12 +1894,12 @@ void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vert } } -void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) { STBTT_free(bitmap, userdata); } -unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) { int ix0,iy0,ix1,iy1; stbtt__bitmap gbm; @@ -1930,12 +1936,12 @@ unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float sc return gbm.pixels; } -unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); } -void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) { int ix0,iy0; stbtt_vertex *vertices; @@ -1954,27 +1960,27 @@ void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *ou STBTT_free(vertices, info->userdata); } -void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); } -unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); } -void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); } -unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); } -void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) { stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); } @@ -1985,7 +1991,7 @@ void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output // // This is SUPER-CRAPPY packing to keep source code small -extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake @@ -2030,7 +2036,7 @@ extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font return bottom_y; } -void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; @@ -2133,7 +2139,7 @@ static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rect // 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) +STBTT_DEF 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; @@ -2163,13 +2169,13 @@ int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int return 1; } -void stbtt_PackEnd (stbtt_pack_context *spc) +STBTT_DEF 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_DEF 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); @@ -2301,7 +2307,7 @@ static float stbtt__oversample_shift(int oversample) 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_DEF 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; @@ -2410,7 +2416,7 @@ int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int f return return_value; } -int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF 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; @@ -2421,7 +2427,7 @@ int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int fo 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) +STBTT_DEF 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; @@ -2494,14 +2500,14 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 return i; } -int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) { return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2); } // returns results in whatever encoding you request... but note that 2-byte encodings // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare -const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) { stbtt_int32 i,count,stringOffset; stbtt_uint8 *fc = font->data; @@ -2598,7 +2604,7 @@ static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *nam return 0; } -int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) { stbtt_int32 i; for (i=0;;++i) { From abe81006dbde19dd280eb2d02152d9aae5904d7d Mon Sep 17 00:00:00 2001 From: Laura Dennis-Jordan Date: Thu, 5 Feb 2015 20:49:04 +0100 Subject: [PATCH 02/23] =?UTF-8?q?Fixed=20bug=20where=20NEON=20code=20was?= =?UTF-8?q?=20#ifdef=E2=80=99d=20out=20on=20GCC/clang=20even=20where=20exp?= =?UTF-8?q?licitly=20requested.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index c3945c2..a19375c 100644 --- a/stb_image.h +++ b/stb_image.h @@ -624,7 +624,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_FREE(p) free(p) #endif -#if defined(__GNUC__) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, // (but compiling with -msse2 allows the compiler to use SSE2 everywhere; // this is just broken and gcc are jerks for not fixing it properly From 4b0c6f6634b62aada5426ea556574717d1095a45 Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Tue, 17 Feb 2015 01:21:40 -0800 Subject: [PATCH 03/23] stb_image: NEON and SSE2 SIMD detection fixes. This fixes two things. First, the logic to disable SSE2 on GCC unless "-msse2" was not specific enough, and ended up disabling SIMD support on NEON targets entirely. Shuffle the detection logic around to make that bit x86-specific. Second, 32-bit MinGW assumes 16-byte aligned stacks, but this is not in the Windows ABI and hence DLLs and callbacks don't necessarily provide it. This caused a crash. This can be fixed by providing the right command-line option, which we have no control over. As a compromise, disable the SSE2 path on MinGW unless a specific #define explained in the comments is set. That way, we default to safe (never-crashing) behavior unless the user explicitly signals they know what they're doing. --- stb_image.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index c3945c2..2af8e3a 100644 --- a/stb_image.h +++ b/stb_image.h @@ -624,7 +624,12 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_FREE(p) free(p) #endif -#if defined(__GNUC__) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) +#define STBI_X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI_X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, // (but compiling with -msse2 allows the compiler to use SSE2 everywhere; // this is just broken and gcc are jerks for not fixing it properly @@ -632,7 +637,20 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_NO_SIMD #endif -#if !defined(STBI_NO_SIMD) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)) +#if defined(__MINGW32__) && defined(STBI_X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && defined(STBI_X86_TARGET) #define STBI_SSE2 #include From a60912f145eee98164750e35991ee7e3e8fccfde Mon Sep 17 00:00:00 2001 From: Joseph Thomson Date: Fri, 20 Feb 2015 10:12:50 +0000 Subject: [PATCH 04/23] Avoid GCC sign-compare warning. GCC 4.7 gave the warning "signed and unsigned type in conditional expression" because the ternary operator mixes signed and unsigned integers. Fixed by casting to unsigned inside the "if" branch instead of casting the result of the entire conditional. --- stb_image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index c3945c2..80b70b1 100644 --- a/stb_image.h +++ b/stb_image.h @@ -4642,7 +4642,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int } } else { for (i=0; i < (int) s->img_x; ++i) { - stbi__uint32 v = (stbi__uint32) (bpp == 16 ? stbi__get16le(s) : stbi__get32le(s)); + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); int a; out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); From 7579b8a177271db84be9081faec7ac3586397edd Mon Sep 17 00:00:00 2001 From: Cap Petschulat Date: Sun, 22 Feb 2015 10:36:26 -0800 Subject: [PATCH 05/23] Fix the simple truetype example --- stb_truetype.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 56ef47b..6855d54 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -222,11 +222,11 @@ #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation #include "stb_truetype.h" -char ttf_buffer[1<<20]; +unsigned char ttf_buffer[1<<20]; unsigned char temp_bitmap[512*512]; stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs -GLstbtt_uint ftex; +GLuint ftex; void my_stbtt_initfont(void) { @@ -243,6 +243,7 @@ void my_stbtt_initfont(void) void my_stbtt_print(float x, float y, char *text) { // assume orthographic projection with units = screen pixels, origin at top left + glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ftex); glBegin(GL_QUADS); while (*text) { From 30eb4371c82a8d9bbf97e75abe8467981856ea20 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Mar 2015 14:49:58 -0700 Subject: [PATCH 06/23] Change double literals 0.5 to float type --- stb_truetype.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 56ef47b..b5a4735 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -2035,8 +2035,8 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; stbtt_bakedchar *b = chardata + char_index; - int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5); - int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5); + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); q->x0 = round_x + d3d_bias; q->y0 = round_y + d3d_bias; @@ -2427,8 +2427,8 @@ void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_in 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); + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); q->x0 = x; q->y0 = y; q->x1 = x + b->xoff2 - b->xoff; From ffe447630d177c4f262407e4b47482ccb21adc84 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Mar 2015 14:54:47 -0700 Subject: [PATCH 07/23] Couple of places should be using STBTT_memset instead of memset --- stb_truetype.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 56ef47b..fe66eb6 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -2189,7 +2189,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i for (j=0; j < h; ++j) { int i; unsigned int total; - memset(buffer, 0, kernel_width); + STBTT_memset(buffer, 0, kernel_width); total = 0; @@ -2243,7 +2243,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i for (j=0; j < w; ++j) { int i; unsigned int total; - memset(buffer, 0, kernel_width); + STBTT_memset(buffer, 0, kernel_width); total = 0; From 80176ae4a144d142756aae3176eb8372da3bcb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Tue, 24 Mar 2015 11:22:20 -0700 Subject: [PATCH 08/23] Remove unused variables in write_hdr_scanline. Fixes #90. --- stb_image_write.h | 1 - 1 file changed, 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 5a449d9..35dea0c 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -297,7 +297,6 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra /* RLE each component separately */ for (c=0; c < 4; c++) { unsigned char *comp = &scratch[width*c]; - int runstart = 0, head = 0, rlerun = 0; x = 0; while (x < width) { From c500a9037565053f7763eadf3d7b3806072fb8d4 Mon Sep 17 00:00:00 2001 From: Nicolas Guillemot Date: Sun, 29 Mar 2015 03:03:09 -0700 Subject: [PATCH 09/23] added stbi_vertically_flip_on_load --- stb_image.h | 56 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/stb_image.h b/stb_image.h index c3945c2..1f4afb8 100644 --- a/stb_image.h +++ b/stb_image.h @@ -487,6 +487,8 @@ STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultipl // or just pass them through "as-is" STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); +// flip the image vertically. useful for opengl image loading. +STBIDEF void stbi_vertically_flip_on_load(int flag_true_if_should_flip); // ZLIB client - used by PNG, available for other purposes @@ -885,44 +887,74 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); #endif +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_vertically_flip_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { + unsigned char *result = NULL; + + if (0); // get the test chain started #ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); + else if (stbi__jpeg_test(s)) result = stbi__jpeg_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PNG - if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); + else if (stbi__png_test(s)) result = stbi__png_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_BMP - if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); + else if (stbi__bmp_test(s)) result = stbi__bmp_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_GIF - if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); + else if (stbi__gif_test(s)) result = stbi__gif_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PSD - if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); + else if (stbi__psd_test(s)) result = stbi__psd_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PIC - if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); + else if (stbi__pic_test(s)) result = stbi__pic_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PNM - if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); + else if (stbi__pnm_test(s)) result = stbi__pnm_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_HDR - if (stbi__hdr_test(s)) { + else if (stbi__hdr_test(s)) { float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); - return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + result = stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); } #endif #ifndef STBI_NO_TGA // test tga last because it's a crappy test! - if (stbi__tga_test(s)) - return stbi__tga_load(s,x,y,comp,req_comp); + else if (stbi__tga_test(s)) + result = stbi__tga_load(s,x,y,comp,req_comp); #endif - return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); + else + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); + + // post-processing + if (stbi__vertically_flip_on_load) { + int depth = req_comp ? req_comp : *comp; + int row,col,z; + stbi_uc temp; + + for (row = 0; row < *y / 2; row++) { + for (col = 0; col < *x; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * (*x) + col) * depth + z]; + result[(row * (*x) + col) * depth + z] = result[((*y - row - 1) * (*x) + col) * depth + z]; + result[((*y - row - 1) * (*x) + col) * depth + z] = temp; + } + } + } + } + + return result; } #ifndef STBI_NO_STDIO From 8b1d835e16c8600a913ec56864b0e66369db9f37 Mon Sep 17 00:00:00 2001 From: Tim Kelsey Date: Wed, 8 Apr 2015 15:24:46 +0100 Subject: [PATCH 10/23] Adding memory and assert defines to stb_image_write --- stb_image_write.h | 87 +++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 5a449d9..5eb6c3f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v0.97 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 no warranty implied; use at your own risk @@ -9,6 +9,10 @@ in the file that you want to have the implementation. + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + You can optionally define STBI_MEMMOVE and STBI_MEMCPY if the default semantics of + memmove and memcpy would be incompatible with your choice of malloc et al. Will probably not work correctly with strict-aliasing optimizations. @@ -32,7 +36,7 @@ USAGE: int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data); Each function returns 0 on failure and non-0 on success. - + The functions create an image file defined by the parameters. The image is a rectangle of pixels stored from left-to-right, top-to-bottom. Each pixel contains 'comp' channels of data stored interleaved with 8-bits @@ -45,7 +49,7 @@ USAGE: PNG creates output files with the same number of components as the input. The BMP format expands Y to RGB in the file format and does not output alpha. - + PNG supports writing rectangles of data even when the bytes storing rows of data are not consecutive in memory (e.g. sub-rectangles of a larger image), by supplying the stride between the beginning of adjacent rows. The other @@ -67,6 +71,8 @@ CREDITS: Jean-Sebastien Guay Bugfixes: Chribba@github + STBI_MALLOC etc: + callidus@github */ #ifndef INCLUDE_STB_IMAGE_WRITE_H @@ -93,9 +99,29 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl #include #include #include -#include #include +#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,sz) realloc(p,sz) +#define STBI_FREE(p) free(p) +#define STBI_MEMMOVE(a,b,sz) memmove(a,b,sz) +#define STBI_MEMCPY(a,b,sz) memcpy(a,b,sz) +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; @@ -113,7 +139,7 @@ static void writefv(FILE *f, const char *fmt, va_list v) b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24); fwrite(b,4,1,f); break; } default: - assert(0); + STBI_ASSERT(0); return; } } @@ -135,7 +161,7 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, if (y <= 0) return; - if (vdir < 0) + if (vdir < 0) j_end = -1, j = y-1; else j_end = y, j = 0; @@ -232,7 +258,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) { unsigned char lengthbyte = (unsigned char) (length+128); - assert(length+128 <= 255); + STBI_ASSERT(length+128 <= 255); fwrite(&lengthbyte, 1, 1, f); fwrite(&databyte, 1, 1, f); } @@ -240,7 +266,7 @@ void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) void stbiw__write_dump_data(FILE *f, int length, unsigned char *data) { unsigned char lengthbyte = (unsigned char )(length & 0xff); - assert(length <= 128); // inconsistent with spec but consistent with official code + STBI_ASSERT(length <= 128); // inconsistent with spec but consistent with official code fwrite(&lengthbyte, 1, 1, f); fwrite(data, length, 1, f); } @@ -321,7 +347,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd // find next byte after run while (r < width && comp[r] == comp[x]) - ++r; + ++r; // output run up to r while (x < r) { int len = r-x; @@ -343,12 +369,12 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da f = fopen(filename, "wb"); if (f) { /* Each component is stored separately. Allocate scratch space for full output scanline. */ - unsigned char *scratch = (unsigned char *) malloc(x*4); + unsigned char *scratch = (unsigned char *) STBI_MALLOC(x*4); fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" ); fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x); for(i=0; i < y; i++) stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x); - free(scratch); + STBI_FREE(scratch); fclose(f); } return f != NULL; @@ -368,13 +394,13 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) -#define stbiw__sbfree(a) ((a) ? free(stbiw__sbraw(a)),0 : 0) +#define stbiw__sbfree(a) ((a) ? STBI_FREE(stbiw__sbraw(a)),0 : 0) static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) { int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; - void *p = realloc(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); - assert(p); + void *p = STBI_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); + STBI_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; *arr = (void *) ((int *) p + 2); @@ -459,7 +485,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l i=0; while (i < data_len-3) { - // hash next 3 bytes of data to be compressed + // hash next 3 bytes of data to be compressed int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; unsigned char *bestloc = 0; unsigned char **hlist = hash_table[h]; @@ -472,7 +498,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } // when hash table entry is too long, delete half the entries if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { - memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + STBI_MEMCPY(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); stbiw__sbn(hash_table[h]) = quality; } stbiw__sbpush(hash_table[h],data+i); @@ -495,7 +521,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l if (bestloc) { int d = (int) (data+i - bestloc); // distance back - assert(d <= 32767 && best <= 258); + STBI_ASSERT(d <= 32767 && best <= 258); for (j=0; best > lengthc[j+1]-1; ++j); stbiw__zlib_huff(j+257); if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); @@ -536,7 +562,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } *out_len = stbiw__sbn(out); // make returned pointer freeable - memmove(stbiw__sbraw(out), out, *out_len); + STBI_MEMMOVE(stbiw__sbraw(out), out, *out_len); return (unsigned char *) stbiw__sbraw(out); } @@ -583,8 +609,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in if (stride_bytes == 0) stride_bytes = x * n; - filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0; - line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; } + filt = (unsigned char *) STBI_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBI_MALLOC(x * n); if (!line_buffer) { STBI_FREE(filt); return 0; } for (j=0; j < y; ++j) { static int mapping[] = { 0,1,2,3,4 }; static int firstmap[] = { 0,1,0,5,6 }; @@ -623,20 +649,20 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in } // when we get here, best contains the filter type, and line_buffer contains the data filt[j*(x*n+1)] = (unsigned char) best; - memcpy(filt+j*(x*n+1)+1, line_buffer, x*n); + STBI_MEMCPY(filt+j*(x*n+1)+1, line_buffer, x*n); } - free(line_buffer); + STBI_FREE(line_buffer); zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory - free(filt); + STBI_FREE(filt); if (!zlib) return 0; // each tag requires 12 bytes of overhead - out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12); + out = (unsigned char *) STBI_MALLOC(8 + 12+13 + 12+zlen + 12); if (!out) return 0; *out_len = 8 + 12+13 + 12+zlen + 12; o=out; - memcpy(o,sig,8); o+= 8; + STBI_MEMCPY(o,sig,8); o+= 8; stbiw__wp32(o, 13); // header length stbiw__wptag(o, "IHDR"); stbiw__wp32(o, x); @@ -650,14 +676,14 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in stbiw__wp32(o, zlen); stbiw__wptag(o, "IDAT"); - memcpy(o, zlib, zlen); o += zlen; free(zlib); + STBI_MEMCPY(o, zlib, zlen); o += zlen; STBI_FREE(zlib); stbiw__wpcrc(&o, zlen); stbiw__wp32(o,0); stbiw__wptag(o, "IEND"); stbiw__wpcrc(&o,0); - assert(o == out + *out_len); + STBI_ASSERT(o == out + *out_len); return out; } @@ -669,16 +695,17 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (!png) return 0; f = fopen(filename, "wb"); - if (!f) { free(png); return 0; } + if (!f) { STBI_FREE(png); return 0; } fwrite(png, 1, len, f); fclose(f); - free(png); + STBI_FREE(png); return 1; } #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history - + 0.98 (2015-04-08) + added STBI_MALLOC, STBI_ASSERT etc 0.97 (2015-01-18) fixed HDR asserts, rewrote HDR rle logic 0.96 (2015-01-17) From b2d440cfb5f01e1c454e1b5d722245b24b046d19 Mon Sep 17 00:00:00 2001 From: Martins Mozeiko Date: Sat, 11 Apr 2015 15:49:56 -0700 Subject: [PATCH 11/23] Fixing various crashes when loading jpg, png and tga images. --- stb_image.h | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/stb_image.h b/stb_image.h index d74ea19..d77452e 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1144,6 +1144,10 @@ stbi_inline static int stbi__at_eof(stbi__context *s) static void stbi__skip(stbi__context *s, int n) { + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { @@ -1552,6 +1556,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < sizeof(stbi__bmask)/sizeof(*stbi__bmask)); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; @@ -2700,6 +2705,10 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) static int stbi__decode_jpeg_image(stbi__jpeg *j) { int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } j->restart_interval = 0; if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; m = stbi__get_marker(j); @@ -3378,8 +3387,10 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) for (i=0; i < num; ++i) ++sizes[sizelist[i]]; sizes[0] = 0; - for (i=1; i < 16; ++i) + for (i=1; i < 16; ++i) { STBI_ASSERT(sizes[i] <= (1 << i)); + if (sizes[i] > (1 << i)) return stbi__err("bad sizes", "Corrupt PNG"); + } code = 0; for (i=1; i < 16; ++i) { next_code[i] = code; @@ -3387,7 +3398,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) z->firstsymbol[i] = (stbi__uint16) k; code = (code + sizes[i]); if (sizes[i]) - if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt JPEG"); + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); z->maxcode[i] = code << (16-i); // preshift for inner loop code <<= 1; k += sizes[i]; @@ -3556,9 +3567,9 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) p = (stbi_uc *) (zout - dist); if (dist == 1) { // run of one byte; common in images. stbi_uc v = *p; - do *zout++ = v; while (--len); + if (len) do *zout++ = v; while (--len); } else { - do *zout++ = *p++; while (--len); + if (len) do *zout++ = *p++; while (--len); } } } @@ -3587,6 +3598,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) while (n < hlit + hdist) { int c = stbi__zhuffman_decode(a, &z_codelength); STBI_ASSERT(c >= 0 && c < 19); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); if (c < 16) lencodes[n++] = (stbi_uc) c; else if (c == 16) { @@ -4283,6 +4295,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) 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 == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; if (ioff + c.length > idata_limit) { stbi_uc *p; if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; @@ -4799,7 +4812,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int *y = tga_height; if (comp) *comp = tga_comp; - tga_data = (unsigned char*)stbi__malloc( tga_width * tga_height * tga_comp ); + tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); // skip to the data's starting position (offset usually = 0) @@ -5460,6 +5473,7 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) stbi__gif_lzw *p; lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; clear = 1 << lzw_cs; first = 1; codesize = lzw_cs + 1; From 7b726511345ccb1ef5044efa8a1cdd42be872547 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 08:59:49 -0700 Subject: [PATCH 12/23] add stb_voxel_render to standard compilation tests --- stb_voxel_render.h | 4 ++-- tests/test_c_compilation.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/stb_voxel_render.h b/stb_voxel_render.h index 6517b3a..576926e 100644 --- a/stb_voxel_render.h +++ b/stb_voxel_render.h @@ -1183,7 +1183,7 @@ struct stbvox_mesh_maker #endif -// The following are candidate voxel modes. Only modes 0, 1, and 20 are +// The following are candidate voxel modes. Only modes 0, 1, and 20, and 21 are // currently implemented. Reducing the storage-per-quad further // shouldn't improve performance, although obviously it allow you // to create larger worlds without streaming. @@ -1205,7 +1205,7 @@ struct stbvox_mesh_maker // not sure why I only wrote down the above "result data" and didn't preserve // the vertex formats, but here I've tried to reconstruct the designs... -// mode # 3 is wrong, one byte too large +// mode # 3 is wrong, one byte too large, but they may have been an error originally // Mode: 0 1 2 3 4 5 6 10 11 12 20 21 22 23 24 // ============================================================================================================= diff --git a/tests/test_c_compilation.c b/tests/test_c_compilation.c index 2aa85b0..309be5a 100644 --- a/tests/test_c_compilation.c +++ b/tests/test_c_compilation.c @@ -7,6 +7,7 @@ #define STB_HERRINGBONE_WANG_TILE_IMEPLEMENTATIOn #define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION +#define STB_VOXEL_RENDER_IMPLEMENTATION #include "stb_herringbone_wang_tile.h" #include "stb_image.h" @@ -18,6 +19,9 @@ #include "stb_image_resize.h" #include "stb_rect_pack.h" +#define STBVOX_CONFIG_MODE 1 +#include "stb_voxel_render.h" + #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 From 24e50cbd5d8b4e895eed57fe37fa9b67d2405dff Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 09:04:43 -0700 Subject: [PATCH 13/23] remove asserts that are now run-time checks; bump version and update credits; minor whitespace changes; --- stb_image.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/stb_image.h b/stb_image.h index d77452e..ce84828 100644 --- a/stb_image.h +++ b/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.02 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.03 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -143,6 +143,7 @@ Latest revision history: + 2.03 (2015-04-12) additional corruption checking 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG @@ -196,6 +197,7 @@ Sergio Gonzalez Cass Everitt Engin Manap + Martins Mozeiko License: This software is in the public domain. Where that dedication is not @@ -3387,10 +3389,9 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) for (i=0; i < num; ++i) ++sizes[sizelist[i]]; sizes[0] = 0; - for (i=1; i < 16; ++i) { - STBI_ASSERT(sizes[i] <= (1 << i)); - if (sizes[i] > (1 << i)) return stbi__err("bad sizes", "Corrupt PNG"); - } + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); code = 0; for (i=1; i < 16; ++i) { next_code[i] = code; @@ -3567,9 +3568,9 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) p = (stbi_uc *) (zout - dist); if (dist == 1) { // run of one byte; common in images. stbi_uc v = *p; - if (len) do *zout++ = v; while (--len); + if (len) { do *zout++ = v; while (--len); } } else { - if (len) do *zout++ = *p++; while (--len); + if (len) { do *zout++ = *p++; while (--len); } } } } @@ -3597,7 +3598,6 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) n = 0; while (n < hlit + hdist) { int c = stbi__zhuffman_decode(a, &z_codelength); - STBI_ASSERT(c >= 0 && c < 19); if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); if (c < 16) lencodes[n++] = (stbi_uc) c; @@ -6205,6 +6205,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.03 (2015-04-12) add extra corruption checking (mmozeiko) 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG From 040df963c8c483c52f2d68b173d2fda899a213eb Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 09:20:31 -0700 Subject: [PATCH 14/23] modifications to vertical flip API: more consistent name, refactor stbi_load_main to preserve old code, support float HDR path, minor bugfix --- stb_image.h | 104 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/stb_image.h b/stb_image.h index 77e2767..68b5b41 100644 --- a/stb_image.h +++ b/stb_image.h @@ -181,7 +181,7 @@ James "moose2000" Brown (iPhone PNG) Roy Eltham Ben "Disch" Wenger (io callbacks) Luke Graham Omar Cornut (1/2/4-bit PNG) Thomas Ruf - John Bartholomew + Nicolas Guillemot (vertical flip) John Bartholomew Ken Hamada Optimizations & bugfixes Cort Stratton Fabian "ryg" Giesen Blazej Dariusz Roszkowski @@ -489,8 +489,8 @@ STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultipl // or just pass them through "as-is" STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); -// flip the image vertically. useful for opengl image loading. -STBIDEF void stbi_vertically_flip_on_load(int flag_true_if_should_flip); +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); // ZLIB client - used by PNG, available for other purposes @@ -891,66 +891,68 @@ static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); static int stbi__vertically_flip_on_load = 0; -STBIDEF void stbi_vertically_flip_on_load(int flag_true_if_should_flip) +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) { stbi__vertically_flip_on_load = flag_true_if_should_flip; } -static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { - unsigned char *result = NULL; - - if (0); // get the test chain started #ifndef STBI_NO_JPEG - else if (stbi__jpeg_test(s)) result = stbi__jpeg_load(s,x,y,comp,req_comp); + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PNG - else if (stbi__png_test(s)) result = stbi__png_load(s,x,y,comp,req_comp); + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_BMP - else if (stbi__bmp_test(s)) result = stbi__bmp_load(s,x,y,comp,req_comp); + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_GIF - else if (stbi__gif_test(s)) result = stbi__gif_load(s,x,y,comp,req_comp); + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PSD - else if (stbi__psd_test(s)) result = stbi__psd_load(s,x,y,comp,req_comp); + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PIC - else if (stbi__pic_test(s)) result = stbi__pic_load(s,x,y,comp,req_comp); + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_PNM - else if (stbi__pnm_test(s)) result = stbi__pnm_load(s,x,y,comp,req_comp); + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); #endif #ifndef STBI_NO_HDR - else if (stbi__hdr_test(s)) { + if (stbi__hdr_test(s)) { float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); - result = stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); } #endif #ifndef STBI_NO_TGA // test tga last because it's a crappy test! - else if (stbi__tga_test(s)) - result = stbi__tga_load(s,x,y,comp,req_comp); + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp); #endif - else - return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} - // post-processing - if (stbi__vertically_flip_on_load) { +static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result = stbi__load_main(s, x, y, comp, req_comp); + + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; int depth = req_comp ? req_comp : *comp; int row,col,z; stbi_uc temp; - for (row = 0; row < *y / 2; row++) { - for (col = 0; col < *x; col++) { + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { for (z = 0; z < depth; z++) { - temp = result[(row * (*x) + col) * depth + z]; - result[(row * (*x) + col) * depth + z] = result[((*y - row - 1) * (*x) + col) * depth + z]; - result[((*y - row - 1) * (*x) + col) * depth + z] = temp; + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; } } } @@ -959,6 +961,28 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp return result; } +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + int row,col,z; + float temp; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } +} + + #ifndef STBI_NO_STDIO static FILE *stbi__fopen(char const *filename, char const *mode) @@ -989,7 +1013,7 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req unsigned char *result; stbi__context s; stbi__start_file(&s,f); - result = stbi_load_main(&s,x,y,comp,req_comp); + result = stbi__load_flip(&s,x,y,comp,req_comp); if (result) { // need to 'unget' all the characters in the IO buffer fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); @@ -1002,25 +1026,29 @@ STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, i { stbi__context s; stbi__start_mem(&s,buffer,len); - return stbi_load_main(&s,x,y,comp,req_comp); + return stbi__load_flip(&s,x,y,comp,req_comp); } STBIDEF stbi_uc *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); - return stbi_load_main(&s,x,y,comp,req_comp); + return stbi__load_flip(&s,x,y,comp,req_comp); } #ifndef STBI_NO_LINEAR -static 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 - if (stbi__hdr_test(s)) - return stbi__hdr_load(s,x,y,comp,req_comp); + if (stbi__hdr_test(s)) { + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } #endif - data = stbi_load_main(s, x, y, comp, req_comp); + data = stbi__load_flip(s, x, y, comp, req_comp); if (data) return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); @@ -1030,14 +1058,14 @@ STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, in { stbi__context s; stbi__start_mem(&s,buffer,len); - return stbi_loadf_main(&s,x,y,comp,req_comp); + return stbi__loadf_main(&s,x,y,comp,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); - return stbi_loadf_main(&s,x,y,comp,req_comp); + return stbi__loadf_main(&s,x,y,comp,req_comp); } #ifndef STBI_NO_STDIO @@ -1055,7 +1083,7 @@ STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_ { stbi__context s; stbi__start_file(&s,f); - return stbi_loadf_main(&s,x,y,comp,req_comp); + return stbi__loadf_main(&s,x,y,comp,req_comp); } #endif // !STBI_NO_STDIO From f22efc6151e4855b03b739845d34ab28f62483a0 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 09:26:16 -0700 Subject: [PATCH 15/23] update credits/docs --- stb_image.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stb_image.h b/stb_image.h index 4549787..f41fcd9 100644 --- a/stb_image.h +++ b/stb_image.h @@ -144,6 +144,7 @@ Latest revision history: 2.03 (2015-04-12) additional corruption checking + stbi_set_flip_vertically_on_load 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG @@ -198,6 +199,7 @@ Cass Everitt Engin Manap Martins Mozeiko + Joseph Thomson License: This software is in the public domain. Where that dedication is not @@ -6265,7 +6267,8 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: - 2.03 (2015-04-12) add extra corruption checking (mmozeiko) + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG From e5fde30800e4f57f7d1b46d7d7891b4fce8273d5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 09:30:05 -0700 Subject: [PATCH 16/23] merge two x86/x64 tests into one; update credits --- stb_image.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/stb_image.h b/stb_image.h index e6e23ea..e2109f9 100644 --- a/stb_image.h +++ b/stb_image.h @@ -200,6 +200,7 @@ Engin Manap Martins Mozeiko Joseph Thomson + Phil Jordan License: This software is in the public domain. Where that dedication is not @@ -630,7 +631,11 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_FREE(p) free(p) #endif -#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) +#define STBI__X86 +#endif + +#if defined(__GNUC__) && defined(STBI__X86) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, // (but compiling with -msse2 allows the compiler to use SSE2 everywhere; // this is just broken and gcc are jerks for not fixing it properly @@ -638,7 +643,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_NO_SIMD #endif -#if !defined(STBI_NO_SIMD) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)) +#if !defined(STBI_NO_SIMD) && defined(STBI__X86) #define STBI_SSE2 #include From 66a75195dc02ce3c2434d0f4d970777e689ed05d Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 09:36:01 -0700 Subject: [PATCH 17/23] rename STBI_X86_TARGET to STBI__X86_TARGET --- stb_image.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/stb_image.h b/stb_image.h index 8653bd3..c00f346 100644 --- a/stb_image.h +++ b/stb_image.h @@ -145,6 +145,7 @@ Latest revision history: 2.03 (2015-04-12) additional corruption checking stbi_set_flip_vertically_on_load + fix NEON support; fix mingw support 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG @@ -633,10 +634,10 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; // x86/x64 detection #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) -#define STBI_X86_TARGET +#define STBI__X86_TARGET #endif -#if defined(__GNUC__) && defined(STBI_X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, // (but compiling with -msse2 allows the compiler to use SSE2 everywhere; // this is just broken and gcc are jerks for not fixing it properly @@ -644,7 +645,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_NO_SIMD #endif -#if defined(__MINGW32__) && defined(STBI_X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) // 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the // Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. // As a result, enabling SSE2 on 32-bit MinGW is dangerous when not @@ -657,7 +658,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI_NO_SIMD #endif -#if !defined(STBI_NO_SIMD) && defined(STBI_X86_TARGET) +#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET) #define STBI_SSE2 #include @@ -6288,6 +6289,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int revision history: 2.03 (2015-04-12) extra corruption checking (mmozeiko) stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG From 24a25458e329908b82d8c2d39d9d3d0618208c88 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 09:36:44 -0700 Subject: [PATCH 18/23] update version number --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index afe30c2..780ccc5 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ single-file public domain libraries for C/C++ library | lastest version | category | description --------------------- | ---- | -------- | -------------------------------- **stb_vorbis.c** | 1.04 | audio | decode ogg vorbis files from file/memory to float/16-bit signed output -**stb_image.h** | 2.02 | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC +**stb_image.h** | 2.03 | 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.97 | graphics | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | resize images larger/smaller with good quality From ab6aaa85bee044ece66631f45630b44b55788d9b Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 12:36:06 -0700 Subject: [PATCH 19/23] credits, STBTT_STATIC docs --- stb_truetype.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/stb_truetype.h b/stb_truetype.h index 9f54318..5442413 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.02 - public domain +// stb_truetype.h - v1.03 - public domain // authored from 2009-2014 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -34,12 +34,16 @@ // Johan Duparc // Hou Qiming // Fabian "ryg" Giesen +// Martins Mozeiko +// Cap Petschulat +// Omar Cornut // // Misc other: // Ryan Gordon // // VERSION HISTORY // +// 1.03 (2015-04-12) STBTT_STATIC, various fixes // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match // non-oversampled; STBTT_POINT_SIZE for packed case only @@ -83,6 +87,9 @@ // before the #include of this file. This expands out the actual // implementation into that C/C++ file. // +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// // 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 From a7ee207475f59a4db0786d96158e13bca29312dd Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 12:45:23 -0700 Subject: [PATCH 20/23] fix missing free in the new rectangle packing remove unneeded (but harmless) statements --- stb_truetype.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 5442413..f304b7b 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -37,6 +37,7 @@ // Martins Mozeiko // Cap Petschulat // Omar Cornut +// github:aloucks // // Misc other: // Ryan Gordon @@ -1054,7 +1055,6 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; - stbtt_uint16 item, offset, start, end; // do a binary search of the segments stbtt_uint32 endCount = index_map + 14; @@ -1071,8 +1071,8 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep // now decrement to bias correctly to find smallest search -= 2; while (entrySelector) { + stbtt_uint16 end; searchRange >>= 1; - start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2); end = ttUSHORT(data + search + searchRange*2); if (unicode_codepoint > end) search += searchRange*2; @@ -1080,19 +1080,21 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep } search += 2; - item = (stbtt_uint16) ((search - endCount) >> 1); + { + stbtt_uint16 offset, start; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); - start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - end = ttUSHORT(data + index_map + 14 + 2 + 2*item); - if (unicode_codepoint < start) - return 0; + STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + if (unicode_codepoint < start) + return 0; - offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); - if (offset == 0) - return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); - return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } } else if (format == 12 || format == 13) { stbtt_uint32 ngroups = ttULONG(data+index_map+12); stbtt_int32 low,high; @@ -2421,6 +2423,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd } } + STBTT_free(rects, spc->user_allocator_context); return return_value; } From 8a0a882f53d18cb34416ac04d848a08484832378 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sun, 12 Apr 2015 12:46:36 -0700 Subject: [PATCH 21/23] stb_truetype version update --- README.md | 2 +- stb_truetype.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 780ccc5..778aa5f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ library | lastest version | category | description --------------------- | ---- | -------- | -------------------------------- **stb_vorbis.c** | 1.04 | audio | decode ogg vorbis files from file/memory to float/16-bit signed output **stb_image.h** | 2.03 | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC -**stb_truetype.h** | 1.02 | graphics | parse, decode, and rasterize characters from truetype fonts +**stb_truetype.h** | 1.03 | graphics | parse, decode, and rasterize characters from truetype fonts **stb_image_write.h** | 0.97 | 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 diff --git a/stb_truetype.h b/stb_truetype.h index f304b7b..26aba20 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -44,7 +44,7 @@ // // VERSION HISTORY // -// 1.03 (2015-04-12) STBTT_STATIC, various fixes +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match // non-oversampled; STBTT_POINT_SIZE for packed case only From 00b1797a2398c8b7a92b195f30224efbf247bdf8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 13 Apr 2015 11:55:24 -0700 Subject: [PATCH 22/23] switch memcpy to memmove for simplicity; rename all STBI_ config macros to STBIW_ to avoid conflict with stb_image.h --- stb_image_write.h | 92 +++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 0bc5708..1048970 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -9,11 +9,6 @@ in the file that you want to have the implementation. - You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. - And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free - You can optionally define STBI_MEMMOVE and STBI_MEMCPY if the default semantics of - memmove and memcpy would be incompatible with your choice of malloc et al. - Will probably not work correctly with strict-aliasing optimizations. ABOUT: @@ -26,6 +21,13 @@ ABOUT: for source code compactness and simplicitly, not optimal image file size or run-time performance. +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + USAGE: There are four functions, one for each image file format: @@ -69,10 +71,10 @@ CREDITS: Baldur Karlsson TGA monochrome: Jean-Sebastien Guay - Bugfixes: - Chribba@github - STBI_MALLOC etc: - callidus@github + misc enhancements: + Tim Kelsey + bugfixes: + github:Chribba */ #ifndef INCLUDE_STB_IMAGE_WRITE_H @@ -101,25 +103,27 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl #include #include -#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC) +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC) // ok -#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) // ok #else -#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC." +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC." #endif -#ifndef STBI_MALLOC -#define STBI_MALLOC(sz) malloc(sz) -#define STBI_REALLOC(p,sz) realloc(p,sz) -#define STBI_FREE(p) free(p) -#define STBI_MEMMOVE(a,b,sz) memmove(a,b,sz) -#define STBI_MEMCPY(a,b,sz) memcpy(a,b,sz) +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,sz) realloc(p,sz) +#define STBIW_FREE(p) free(p) +#endif +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) #endif -#ifndef STBI_ASSERT + +#ifndef STBIW_ASSERT #include -#define STBI_ASSERT(x) assert(x) +#define STBIW_ASSERT(x) assert(x) #endif typedef unsigned int stbiw_uint32; @@ -139,7 +143,7 @@ static void writefv(FILE *f, const char *fmt, va_list v) b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24); fwrite(b,4,1,f); break; } default: - STBI_ASSERT(0); + STBIW_ASSERT(0); return; } } @@ -258,7 +262,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) { unsigned char lengthbyte = (unsigned char) (length+128); - STBI_ASSERT(length+128 <= 255); + STBIW_ASSERT(length+128 <= 255); fwrite(&lengthbyte, 1, 1, f); fwrite(&databyte, 1, 1, f); } @@ -266,7 +270,7 @@ void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) void stbiw__write_dump_data(FILE *f, int length, unsigned char *data) { unsigned char lengthbyte = (unsigned char )(length & 0xff); - STBI_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code fwrite(&lengthbyte, 1, 1, f); fwrite(data, length, 1, f); } @@ -368,12 +372,12 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da f = fopen(filename, "wb"); if (f) { /* Each component is stored separately. Allocate scratch space for full output scanline. */ - unsigned char *scratch = (unsigned char *) STBI_MALLOC(x*4); + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" ); fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x); for(i=0; i < y; i++) stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x); - STBI_FREE(scratch); + STBIW_FREE(scratch); fclose(f); } return f != NULL; @@ -393,13 +397,13 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) -#define stbiw__sbfree(a) ((a) ? STBI_FREE(stbiw__sbraw(a)),0 : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) { int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; - void *p = STBI_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); - STBI_ASSERT(p); + void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; *arr = (void *) ((int *) p + 2); @@ -497,7 +501,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } // when hash table entry is too long, delete half the entries if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { - STBI_MEMCPY(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); stbiw__sbn(hash_table[h]) = quality; } stbiw__sbpush(hash_table[h],data+i); @@ -520,7 +524,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l if (bestloc) { int d = (int) (data+i - bestloc); // distance back - STBI_ASSERT(d <= 32767 && best <= 258); + STBIW_ASSERT(d <= 32767 && best <= 258); for (j=0; best > lengthc[j+1]-1; ++j); stbiw__zlib_huff(j+257); if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); @@ -561,7 +565,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } *out_len = stbiw__sbn(out); // make returned pointer freeable - STBI_MEMMOVE(stbiw__sbraw(out), out, *out_len); + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); return (unsigned char *) stbiw__sbraw(out); } @@ -608,8 +612,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in if (stride_bytes == 0) stride_bytes = x * n; - filt = (unsigned char *) STBI_MALLOC((x*n+1) * y); if (!filt) return 0; - line_buffer = (signed char *) STBI_MALLOC(x * n); if (!line_buffer) { STBI_FREE(filt); return 0; } + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } for (j=0; j < y; ++j) { static int mapping[] = { 0,1,2,3,4 }; static int firstmap[] = { 0,1,0,5,6 }; @@ -648,20 +652,20 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in } // when we get here, best contains the filter type, and line_buffer contains the data filt[j*(x*n+1)] = (unsigned char) best; - STBI_MEMCPY(filt+j*(x*n+1)+1, line_buffer, x*n); + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); } - STBI_FREE(line_buffer); + STBIW_FREE(line_buffer); zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory - STBI_FREE(filt); + STBIW_FREE(filt); if (!zlib) return 0; // each tag requires 12 bytes of overhead - out = (unsigned char *) STBI_MALLOC(8 + 12+13 + 12+zlen + 12); + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); if (!out) return 0; *out_len = 8 + 12+13 + 12+zlen + 12; o=out; - STBI_MEMCPY(o,sig,8); o+= 8; + STBIW_MEMMOVE(o,sig,8); o+= 8; stbiw__wp32(o, 13); // header length stbiw__wptag(o, "IHDR"); stbiw__wp32(o, x); @@ -675,14 +679,16 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in stbiw__wp32(o, zlen); stbiw__wptag(o, "IDAT"); - STBI_MEMCPY(o, zlib, zlen); o += zlen; STBI_FREE(zlib); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); stbiw__wpcrc(&o, zlen); stbiw__wp32(o,0); stbiw__wptag(o, "IEND"); stbiw__wpcrc(&o,0); - STBI_ASSERT(o == out + *out_len); + STBIW_ASSERT(o == out + *out_len); return out; } @@ -694,17 +700,17 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (!png) return 0; f = fopen(filename, "wb"); - if (!f) { STBI_FREE(png); return 0; } + if (!f) { STBIW_FREE(png); return 0; } fwrite(png, 1, len, f); fclose(f); - STBI_FREE(png); + STBIW_FREE(png); return 1; } #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history 0.98 (2015-04-08) - added STBI_MALLOC, STBI_ASSERT etc + added STBIW_MALLOC, STBIW_ASSERT etc 0.97 (2015-01-18) fixed HDR asserts, rewrote HDR rle logic 0.96 (2015-01-17) From 07a598cb2ffe8f567955039dd1f78038a9eee652 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 13 Apr 2015 11:58:04 -0700 Subject: [PATCH 23/23] update stb_image_write version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 778aa5f..eec9e98 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ library | lastest version | category | description **stb_vorbis.c** | 1.04 | audio | decode ogg vorbis files from file/memory to float/16-bit signed output **stb_image.h** | 2.03 | graphics | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC **stb_truetype.h** | 1.03 | graphics | parse, decode, and rasterize characters from truetype fonts -**stb_image_write.h** | 0.97 | graphics | image writing to disk: PNG, TGA, BMP +**stb_image_write.h** | 0.98 | graphics | image writing to disk: PNG, TGA, BMP **stb_image_resize.h** | 0.90 | graphics | resize images larger/smaller with good quality **stb_rect_pack.h** | 0.05 | graphics | simple 2D rectangle packer with decent quality **stretchy_buffer.h** | 1.01 | utility | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++