Merge pull request #21 from jadamcze/warnings

Udpated stb_image and stb_truetype, Fixed compiler warnings.
This commit is contained in:
Mikko Mononen 2014-04-11 11:41:43 +03:00
commit a6d4dddaae
8 changed files with 4180 additions and 3119 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
// stb_truetype.h - v0.3 - public domain - 2009 Sean Barrett / RAD Game Tools // stb_truetype.h - v0.7 - public domain
// authored from 2009-2013 by Sean Barrett / RAD Game Tools
// //
// This library processes TrueType files: // This library processes TrueType files:
// parse files // parse files
@ -9,21 +10,53 @@
// Todo: // Todo:
// non-MS cmaps // non-MS cmaps
// crashproof on bad data // crashproof on bad data
// hinting // hinting? (no longer patented)
// subpixel positioning when rendering bitmap // cleartype-style AA?
// cleartype-style AA // optimize: use simple memory allocator for intermediates
// optimize: build edge-list directly from curves
// optimize: rasterize directly from curves?
// //
// ADDITIONAL CONTRIBUTORS // ADDITIONAL CONTRIBUTORS
// //
// Mikko Mononen: compound shape support, more cmap formats // Mikko Mononen: compound shape support, more cmap formats
// Tor Andersson: kerning, subpixel rendering
// //
// VERSIONS // Bug/warning reports:
// "Zer" on mollyrocket (with fix)
// Cass Everitt
// stoiko (Haemimont Games)
// Brian Hook
// Walter van Niftrik
// //
// VERSION HISTORY
//
// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
// 0.6c (2012-07-24) improve documentation
// 0.6b (2012-07-20) fix a few more warnings
// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
// 0.5 (2011-12-09) bugfixes:
// subpixel glyph renderer computed wrong bounding box
// first vertex of shape can be off-curve (FreeSans)
// 0.4b (2011-12-03) fixed an error in the font baking example
// 0.4 (2011-12-01) kerning, subpixel rendering (tor)
// bugfixes for:
// codepoint-to-glyph conversion using table fmt=12
// codepoint-to-glyph conversion using table fmt=4
// stbtt_GetBakedQuad with non-square texture (Zer)
// updated Hello World! sample to use kerning and subpixel
// fixed some warnings
// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
// userdata, malloc-from-userdata, non-zero fill (STB) // userdata, malloc-from-userdata, non-zero fill (STB)
// 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.2 (2009-03-11) Fix unsigned/signed char warnings
// 0.1 (2009-03-09) First public release // 0.1 (2009-03-09) First public release
// //
// LICENSE
//
// This software is in the public domain. Where that dedication is not
// recognized, you are granted a perpetual, irrevokable license to copy
// and modify this file as you see fit.
//
// USAGE // USAGE
// //
// Include this file in whatever places neeed to refer to it. In ONE C/C++ // Include this file in whatever places neeed to refer to it. In ONE C/C++
@ -32,8 +65,6 @@
// before the #include of this file. This expands out the actual // before the #include of this file. This expands out the actual
// implementation into that C/C++ file. // implementation into that C/C++ file.
// //
// Look at the header-file sections below for the API, but here's a quick skim:
//
// Simple 3D API (don't ship this, but it's fine for tools and quick start, // Simple 3D API (don't ship this, but it's fine for tools and quick start,
// and you can cut and paste from it to move to more advanced) // and you can cut and paste from it to move to more advanced)
// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
@ -51,6 +82,83 @@
// Character advance/positioning // Character advance/positioning
// stbtt_GetCodepointHMetrics() // stbtt_GetCodepointHMetrics()
// stbtt_GetFontVMetrics() // stbtt_GetFontVMetrics()
// stbtt_GetCodepointKernAdvance()
//
// ADDITIONAL DOCUMENTATION
//
// Immediately after this block comment are a series of sample programs.
//
// After the sample programs is the "header file" section. This section
// includes documentation for each API function.
//
// Some important concepts to understand to use this library:
//
// Codepoint
// Characters are defined by unicode codepoints, e.g. 65 is
// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
// the hiragana for "ma".
//
// Glyph
// A visual character shape (every codepoint is rendered as
// some glyph)
//
// Glyph index
// A font-specific integer ID representing a glyph
//
// Baseline
// Glyph shapes are defined relative to a baseline, which is the
// bottom of uppercase characters. Characters extend both above
// and below the baseline.
//
// Current Point
// As you draw text to the screen, you keep track of a "current point"
// which is the origin of each character. The current point's vertical
// position is the baseline. Even "baked fonts" use this model.
//
// Vertical Font Metrics
// The vertical qualities of the font, used to vertically position
// and space the characters. See docs for stbtt_GetFontVMetrics.
//
// Font Size in Pixels or Points
// The preferred interface for specifying font sizes in stb_truetype
// is to specify how tall the font's vertical extent should be in pixels.
// If that sounds good enough, skip the next paragraph.
//
// Most font APIs instead use "points", which are a common typographic
// measurement for describing font size, defined as 72 points per inch.
// stb_truetype provides a point API for compatibility. However, true
// "per inch" conventions don't make much sense on computer displays
// since they different monitors have different number of pixels per
// inch. For example, Windows traditionally uses a convention that
// there are 96 pixels per inch, thus making 'inch' measurements have
// nothing to do with inches, and thus effectively defining a point to
// be 1.333 pixels. Additionally, the TrueType font data provides
// an explicit scale factor to scale a given font's glyphs to points,
// but the author has observed that this scale factor is often wrong
// for non-commercial fonts, thus making fonts scaled in points
// according to the TrueType spec incoherently sized in practice.
//
// ADVANCED USAGE
//
// Quality:
//
// - Use the functions with Subpixel at the end to allow your characters
// to have subpixel positioning. Since the font is anti-aliased, not
// hinted, this is very import for quality. (This is not possible with
// baked fonts.)
//
// - Kerning is now supported, and if you're supporting subpixel rendering
// then kerning is worth using to give your text a polished look.
//
// Performance:
//
// - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
// if you don't do this, stb_truetype is forced to do the conversion on
// every call.
//
// - There are a lot of memory allocations. We should modify it to take
// a temp buffer and allocate from the temp buffer (without freeing),
// should help performance a lot.
// //
// NOTES // NOTES
// //
@ -64,14 +172,14 @@
// recommend it. // recommend it.
// //
// //
// SOURCE STATISTICS (based on v0.3, 1800 LOC) // SOURCE STATISTICS (based on v0.6c, 2050 LOC)
// //
// Documentation & header file 350 LOC \___ 500 LOC documentation // Documentation & header file 520 LOC \___ 660 LOC documentation
// Sample code 140 LOC / // Sample code 140 LOC /
// Truetype parsing 580 LOC ---- 600 LOC TrueType // Truetype parsing 620 LOC ---- 620 LOC TrueType
// Software rasterization 240 LOC \ . // Software rasterization 240 LOC \ .
// Curve tesselation 120 LOC \__ 500 LOC Bitmap creation // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
// Bitmap management 70 LOC / // Bitmap management 100 LOC /
// Baked bitmap interface 70 LOC / // Baked bitmap interface 70 LOC /
// Font name matching & access 150 LOC ---- 150 // Font name matching & access 150 LOC ---- 150
// C runtime library abstraction 60 LOC ---- 60 // C runtime library abstraction 60 LOC ---- 60
@ -92,7 +200,7 @@
char ttf_buffer[1<<20]; char ttf_buffer[1<<20];
unsigned char temp_bitmap[512*512]; unsigned char temp_bitmap[512*512];
stbtt_chardata cdata[96]; // ASCII 32..126 is 95 glyphs stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
GLstbtt_uint ftex; GLstbtt_uint ftex;
void my_stbtt_initfont(void) void my_stbtt_initfont(void)
@ -177,33 +285,41 @@ int main(int argc, char **argv)
// Complete program: print "Hello World!" banner, with bugs // Complete program: print "Hello World!" banner, with bugs
// //
#if 0 #if 0
char buffer[24<<20];
unsigned char screen[20][79];
int main(int arg, char **argv) int main(int arg, char **argv)
{ {
unsigned char screen[20][79]; stbtt_fontinfo font;
int i,j, pos=0; int i,j,ascent,baseline,ch=0;
float scale; float scale, xpos=0;
char *text = "Heljo World!"; char *text = "Heljo World!";
fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
stbtt_InitFont(&font, buffer, 0); stbtt_InitFont(&font, buffer, 0);
scale = stbtt_ScaleForPixelHeight(&font, 16); scale = stbtt_ScaleForPixelHeight(&font, 15);
memset(screen, 0, sizeof(screen)); stbtt_GetFontVMetrics(&font, &ascent,0,0);
baseline = (int) (ascent*scale);
while (*text) { while (text[ch]) {
int advance,lsb,x0,y0,x1,y1, newpos, baseline=13; int advance,lsb,x0,y0,x1,y1;
stbtt_GetCodepointHMetrics(&font, *text, &advance, &lsb); float x_shift = xpos - (float) floor(xpos);
stbtt_GetCodepointBitmapBox(&font, *text, scale,scale, &x0,&y0,&x1,&y1); stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
newpos = pos + (int) (lsb * scale) + x0; stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
stbtt_MakeCodepointBitmap(&font, &screen[baseline + y0][newpos], x1-x0,y1-y0, 79, scale,scale, *text); stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
// note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
// because this API is really for baking character bitmaps into textures // because this API is really for baking character bitmaps into textures. if you want to render
pos += (int) (advance * scale); // a sequence of characters, you really need to render each bitmap to a temp buffer, then
++text; // "alpha blend" that into the working buffer
xpos += (advance * scale);
if (text[ch+1])
xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
++ch;
} }
for (j=0; j < 20; ++j) { for (j=0; j < 20; ++j) {
for (i=0; i < 79; ++i) for (i=0; i < 78; ++i)
putchar(" .:ioVM@"[screen[j][i]>>5]); putchar(" .:ioVM@"[screen[j][i]>>5]);
putchar('\n'); putchar('\n');
} }
@ -216,8 +332,10 @@ int main(int arg, char **argv)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
//// ////
//// INTEGRATION WITH RUNTIME LIBRARIES //// INTEGRATION WITH YOUR CODEBASE
//// ////
//// The following sections allow you to supply alternate definitions
//// of C library functions used by stb_truetype.
#ifdef STB_TRUETYPE_IMPLEMENTATION #ifdef STB_TRUETYPE_IMPLEMENTATION
// #define your own (u)stbtt_int8/16/32 before including to override this // #define your own (u)stbtt_int8/16/32 before including to override this
@ -320,6 +438,12 @@ extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // sa
int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
// Call GetBakedQuad with char_index = 'character - first_char', and it // Call GetBakedQuad with char_index = 'character - first_char', and it
// creates the quad you need to draw and advances the current position. // creates the quad you need to draw and advances the current position.
//
// The coordinate system used assumes y increases downwards.
//
// Characters will extend both above and below the current position;
// see discussion of "BASELINE" above.
//
// It's inefficient; you might want to c&p it and optimize it. // It's inefficient; you might want to c&p it and optimize it.
@ -330,25 +454,25 @@ extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // sa
// //
extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
// Each .ttf file may have more than one font. Each has a sequential index // Each .ttf/.ttc file may have more than one font. Each font has a sequential
// number starting from 0. Call this function to get the font offset for a // index number starting from 0. Call this function to get the font offset for
// given index; it returns -1 if the index is out of range. A regular .ttf // a given index; it returns -1 if the index is out of range. A regular .ttf
// file will only define one font and it always be at offset 0, so it will // file will only define one font and it always be at offset 0, so it will
// return '0' for index 0, and -1 for all other indices. You can just skip // return '0' for index 0, and -1 for all other indices. You can just skip
// this step if you know it's that kind of font. // this step if you know it's that kind of font.
// The following structure is defined publically so you can declare one on // The following structure is defined publically so you can declare one on
// the stack or as a global or etc. // the stack or as a global or etc, but you should treat it as opaque.
typedef struct typedef struct stbtt_fontinfo
{ {
void *userdata; void * userdata;
unsigned char *data; // pointer to .ttf file unsigned char * data; // pointer to .ttf file
int fontstart; // offset of start of font int fontstart; // offset of start of font
int numGlyphs; // number of glyphs, needed for range checking int numGlyphs; // number of glyphs, needed for range checking
int loca,head,glyf,hhea,hmtx; // table locations as offset from start of .ttf int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph int indexToLocFormat; // format needed to map from glyph index to glyph
} stbtt_fontinfo; } stbtt_fontinfo;
@ -357,8 +481,8 @@ extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int o
// Given an offset into the file that defines a font, this function builds // 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 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 // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
// need to do anything special to free it, because the contents are a pure // need to do anything special to free it, because the contents are pure
// cache with no additional data structures. Returns 0 on failure. // value data with no additional data structures. Returns 0 on failure.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -385,12 +509,21 @@ extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels)
// scale = pixels / (ascent - descent) // scale = pixels / (ascent - descent)
// so if you prefer to measure height by the ascent only, use a similar calculation. // 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);
// 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); extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
// ascent is the coordinate above the baseline the font extends; descent // 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) // 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... // lineGap is the spacing between one row's descent and the next row's ascent...
// so you should advance the vertical position by "*ascent - *descent + *lineGap" // so you should advance the vertical position by "*ascent - *descent + *lineGap"
// these are expressed in unscaled coordinates // 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);
// the bounding box around all possible characters
extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); extern 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 // leftSideBearing is the offset from the current horizontal position to the left edge of the character
@ -434,6 +567,9 @@ extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *
} stbtt_vertex; } stbtt_vertex;
#endif #endif
extern 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_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); extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
// returns # of vertices and fills *vertices with the pointer to them // returns # of vertices and fills *vertices with the pointer to them
@ -459,11 +595,19 @@ 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 // 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);
// 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); 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);
// the same as above, but you pass in storage for the bitmap in the form // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
// of 'output', with row spacing of 'out_stride' bytes. the bitmap is // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
// clipped to out_w/out_h bytes. call the next function to get the // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
// height and width and positioning info // 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);
// 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); extern 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 // get the bbox of the bitmap centered around the glyph origin; so the
@ -472,11 +616,19 @@ extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoin
// (Note that the bitmap uses y-increases-down, but the shape uses // (Note that the bitmap uses y-increases-down, but the shape uses
// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
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 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);
extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
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); // 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);
//extern void stbtt_get_true_bbox(stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
// @TODO: don't expose this structure // @TODO: don't expose this structure
typedef struct typedef struct
@ -485,7 +637,7 @@ typedef struct
unsigned char *pixels; unsigned char *pixels;
} stbtt__bitmap; } 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, int x_off, int y_off, int invert, void *userdata); 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);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -524,7 +676,7 @@ extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const ch
// returns 1/0 whether the first string interpreted as utf8 is identical to // 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 // the second string interpreted as big-endian utf16... useful for strings from next func
extern char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); extern 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) // returns the string (which may be big-endian double byte, e.g. for unicode)
// and puts the length in bytes in *length. // and puts the length in bytes in *length.
// //
@ -544,21 +696,21 @@ enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
STBTT_UNICODE_EID_UNICODE_1_1 =1, STBTT_UNICODE_EID_UNICODE_1_1 =1,
STBTT_UNICODE_EID_ISO_10646 =2, STBTT_UNICODE_EID_ISO_10646 =2,
STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
STBTT_UNICODE_EID_UNICODE_2_0_FULL=4, STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
}; };
enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
STBTT_MS_EID_SYMBOL =0, STBTT_MS_EID_SYMBOL =0,
STBTT_MS_EID_UNICODE_BMP =1, STBTT_MS_EID_UNICODE_BMP =1,
STBTT_MS_EID_SHIFTJIS =2, STBTT_MS_EID_SHIFTJIS =2,
STBTT_MS_EID_UNICODE_FULL =10, STBTT_MS_EID_UNICODE_FULL =10
}; };
enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7, STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
}; };
enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
@ -568,7 +720,7 @@ enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D, STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
}; };
enum { // languageID for STBTT_PLATFORM_ID_MAC enum { // languageID for STBTT_PLATFORM_ID_MAC
@ -578,7 +730,7 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19, STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
}; };
#ifdef __cplusplus #ifdef __cplusplus
@ -630,7 +782,7 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
static int stbtt__isfont(const stbtt_uint8 *font) static int stbtt__isfont(const stbtt_uint8 *font)
{ {
// check the version number // check the version number
if (stbtt_tag(font, "1")) return 1; // TrueType 1 if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1
if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
@ -679,12 +831,13 @@ int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontsta
info->data = data; info->data = data;
info->fontstart = fontstart; info->fontstart = fontstart;
cmap = stbtt__find_table(data, fontstart, "cmap"); cmap = stbtt__find_table(data, fontstart, "cmap"); // required
info->loca = stbtt__find_table(data, fontstart, "loca"); info->loca = stbtt__find_table(data, fontstart, "loca"); // required
info->head = stbtt__find_table(data, fontstart, "head"); info->head = stbtt__find_table(data, fontstart, "head"); // required
info->glyf = stbtt__find_table(data, fontstart, "glyf"); info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
info->hhea = stbtt__find_table(data, fontstart, "hhea"); info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
return 0; return 0;
@ -746,7 +899,7 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
stbtt_uint16 item, offset, start, end; stbtt_uint16 item, offset, start;
// do a binary search of the segments // do a binary search of the segments
stbtt_uint32 endCount = index_map + 14; stbtt_uint32 endCount = index_map + 14;
@ -763,11 +916,9 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
// now decrement to bias correctly to find smallest // now decrement to bias correctly to find smallest
search -= 2; search -= 2;
while (entrySelector) { while (entrySelector) {
stbtt_uint16 start, end; stbtt_uint16 end;
searchRange >>= 1; searchRange >>= 1;
start = ttUSHORT(data + search + 2 + segcount*2 + 2);
end = ttUSHORT(data + search + 2); end = ttUSHORT(data + search + 2);
start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
end = ttUSHORT(data + search + searchRange*2); end = ttUSHORT(data + search + searchRange*2);
if (unicode_codepoint > end) if (unicode_codepoint > end)
search += searchRange*2; search += searchRange*2;
@ -779,31 +930,33 @@ int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 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) if (unicode_codepoint < start)
return 0; return 0;
offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
if (offset == 0) if (offset == 0)
return unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item); 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) { } else if (format == 12 || format == 13) {
stbtt_uint16 ngroups = ttUSHORT(data+index_map+6); stbtt_uint32 ngroups = ttULONG(data+index_map+12);
stbtt_int32 low,high; stbtt_int32 low,high;
low = 0; high = (stbtt_int32)ngroups; low = 0; high = (stbtt_int32)ngroups;
// Binary search the right group. // Binary search the right group.
while (low <= high) { while (low < high) {
stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
if ((stbtt_uint32) unicode_codepoint < start_char) if ((stbtt_uint32) unicode_codepoint < start_char)
high = mid-1; high = mid;
else if ((stbtt_uint32) unicode_codepoint > end_char) else if ((stbtt_uint32) unicode_codepoint > end_char)
low = mid+1; low = mid+1;
else { else {
stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
if (format == 12)
return start_glyph + unicode_codepoint-start_char; return start_glyph + unicode_codepoint-start_char;
else // format == 13
return start_glyph;
} }
} }
return 0; // not found return 0; // not found
@ -818,13 +971,13 @@ int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, s
return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
} }
static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int16 x, stbtt_int16 y, stbtt_int16 cx, stbtt_int16 cy) static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
{ {
v->type = type; v->type = type;
v->x = x; v->x = (stbtt_int16) x;
v->y = y; v->y = (stbtt_int16) y;
v->cx = cx; v->cx = (stbtt_int16) cx;
v->cy = cy; v->cy = (stbtt_int16) cy;
} }
static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
@ -862,6 +1015,31 @@ int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, in
return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
} }
int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
{
stbtt_int16 numberOfContours;
int g = stbtt__GetGlyfOffset(info, glyph_index);
if (g < 0) return 1;
numberOfContours = ttSHORT(info->data + g);
return numberOfContours == 0;
}
static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
{
if (start_off) {
if (was_off)
stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
} else {
if (was_off)
stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
else
stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
}
return num_vertices;
}
int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
{ {
stbtt_int16 numberOfContours; stbtt_int16 numberOfContours;
@ -879,8 +1057,8 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
if (numberOfContours > 0) { if (numberOfContours > 0) {
stbtt_uint8 flags=0,flagcount; stbtt_uint8 flags=0,flagcount;
stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off; stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
stbtt_int16 x,y,cx,cy,sx,sy; stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
stbtt_uint8 *points; stbtt_uint8 *points;
endPtsOfContours = (data + g + 10); endPtsOfContours = (data + g + 10);
ins = ttUSHORT(data + g + 10 + numberOfContours * 2); ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
@ -888,7 +1066,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
m = n + numberOfContours; // a loose bound on how many vertices we might need m = n + 2*numberOfContours; // a loose bound on how many vertices we might need
vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
if (vertices == 0) if (vertices == 0)
return 0; return 0;
@ -927,7 +1105,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
points += 2; points += 2;
} }
} }
vertices[off+i].x = x; vertices[off+i].x = (stbtt_int16) x;
} }
// now load y coordinates // now load y coordinates
@ -943,32 +1121,46 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
points += 2; points += 2;
} }
} }
vertices[off+i].y = y; vertices[off+i].y = (stbtt_int16) y;
} }
// now convert them to our format // now convert them to our format
num_vertices=0; num_vertices=0;
sx = sy = cx = cy = 0; sx = sy = cx = cy = scx = scy = 0;
for (i=0; i < n; ++i) { for (i=0; i < n; ++i) {
flags = vertices[off+i].type; flags = vertices[off+i].type;
x = (stbtt_int16) vertices[off+i].x; x = (stbtt_int16) vertices[off+i].x;
y = (stbtt_int16) vertices[off+i].y; y = (stbtt_int16) vertices[off+i].y;
if (next_move == i) { if (next_move == i) {
// when we get to the end, we have to close the shape explicitly if (i != 0)
if (i != 0) { num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
if (was_off)
stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
else
stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
}
// now start the new one // now start the new one
stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,x,y,0,0); start_off = !(flags & 1);
next_move = 1 + ttUSHORT(endPtsOfContours+j*2); if (start_off) {
++j; // if we start off with an off-curve point, then when we need to find a point on the curve
was_off = 0; // where we can start, and we need to save some state for when we wraparound.
scx = x;
scy = y;
if (!(vertices[off+i+1].type & 1)) {
// next point is also a curve point, so interpolate an on-point curve
sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
} else {
// otherwise just use the next point as our start point
sx = (stbtt_int32) vertices[off+i+1].x;
sy = (stbtt_int32) vertices[off+i+1].y;
++i; // we're using point i+1 as the starting point, so skip it
}
} else {
sx = x; sx = x;
sy = y; sy = y;
}
stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
was_off = 0;
next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
++j;
} else { } else {
if (!(flags & 1)) { // if it's a curve if (!(flags & 1)) { // if it's a curve
if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
@ -985,12 +1177,7 @@ int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_verte
} }
} }
} }
if (i != 0) { num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
if (was_off)
stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
else
stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
}
} else if (numberOfContours == -1) { } else if (numberOfContours == -1) {
// Compound shapes. // Compound shapes.
int more = 1; int more = 1;
@ -1091,14 +1278,41 @@ void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *ad
} }
} }
int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo * /*info*/, int /*glyph1*/, int /*glyph2*/) int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{ {
stbtt_uint8 *data = info->data + info->kern;
stbtt_uint32 needle, straw;
int l, r, m;
// we only look at the first table. it must be 'horizontal' and format 0.
if (!info->kern)
return 0;
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
return 0;
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
return 0;
l = 0;
r = ttUSHORT(data+10) - 1;
needle = glyph1 << 16 | glyph2;
while (l <= r) {
m = (l + r) >> 1;
straw = ttULONG(data+18+(m*6)); // note: unaligned read
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else
return ttSHORT(data+22+(m*6));
}
return 0; return 0;
} }
int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo * /*info*/, int /*ch1*/, int /*ch2*/) 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 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) void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
@ -1113,12 +1327,26 @@ void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent
if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
} }
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);
*x1 = ttSHORT(info->data + info->head + 40);
*y1 = ttSHORT(info->data + info->head + 42);
}
float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
{ {
int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
return (float) height / fheight; return (float) height / fheight;
} }
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) void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
{ {
STBTT_free(v, info->userdata); STBTT_free(v, info->userdata);
@ -1129,21 +1357,30 @@ void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
// antialiasing software rasterizer // antialiasing software rasterizer
// //
void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) 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; int x0,y0,x1,y1;
if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1))
x0=y0=x1=y1=0; // e.g. space character x0=y0=x1=y1=0; // e.g. space character
// now move to integral bboxes (treating pixels as little squares, what pixels get touched)? // now move to integral bboxes (treating pixels as little squares, what pixels get touched)?
if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x); if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x + shift_x);
if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y); if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y + shift_y);
if (ix1) *ix1 = STBTT_iceil (x1 * scale_x); if (ix1) *ix1 = STBTT_iceil (x1 * scale_x + shift_x);
if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y); if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y + shift_y);
}
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_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) void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
{ {
stbtt_GetGlyphBitmapBox(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y, ix0,iy0,ix1,iy1); stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
} }
typedef struct stbtt__edge { typedef struct stbtt__edge {
@ -1343,7 +1580,7 @@ typedef struct
float x,y; float x,y;
} stbtt__point; } stbtt__point;
static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, int off_x, int off_y, int invert, void *userdata) static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
{ {
float y_scale_inv = invert ? -scale_y : scale_y; float y_scale_inv = invert ? -scale_y : scale_y;
stbtt__edge *e; stbtt__edge *e;
@ -1376,10 +1613,10 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou
e[n].invert = 1; e[n].invert = 1;
a=j,b=k; a=j,b=k;
} }
e[n].x0 = p[a].x * scale_x; e[n].x0 = p[a].x * scale_x + shift_x;
e[n].y0 = p[a].y * y_scale_inv * vsubsample; e[n].y0 = p[a].y * y_scale_inv * vsubsample + shift_y;
e[n].x1 = p[b].x * scale_x; e[n].x1 = p[b].x * scale_x + shift_x;
e[n].y1 = p[b].y * y_scale_inv * vsubsample; e[n].y1 = p[b].y * y_scale_inv * vsubsample + shift_y;
++n; ++n;
} }
} }
@ -1491,13 +1728,13 @@ error:
return NULL; return NULL;
} }
void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata) 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; float scale = scale_x > scale_y ? scale_y : scale_x;
int winding_count, *winding_lengths; int winding_count, *winding_lengths;
stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
if (windings) { if (windings) {
stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert, userdata); stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
STBTT_free(winding_lengths, userdata); STBTT_free(winding_lengths, userdata);
STBTT_free(windings, userdata); STBTT_free(windings, userdata);
} }
@ -1508,7 +1745,7 @@ void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
STBTT_free(bitmap, userdata); STBTT_free(bitmap, userdata);
} }
unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) 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; int ix0,iy0,ix1,iy1;
stbtt__bitmap gbm; stbtt__bitmap gbm;
@ -1521,7 +1758,7 @@ unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, f
scale_y = scale_x; scale_y = scale_x;
} }
stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1); stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
// now we get the size // now we get the size
gbm.w = (ix1 - ix0); gbm.w = (ix1 - ix0);
@ -1538,47 +1775,67 @@ unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, f
if (gbm.pixels) { if (gbm.pixels) {
gbm.stride = gbm.w; gbm.stride = gbm.w;
stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata); stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
} }
} }
STBTT_free(vertices, info->userdata); STBTT_free(vertices, info->userdata);
return gbm.pixels; return gbm.pixels;
} }
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) 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)
{ {
int ix0,iy0; int ix0,iy0;
stbtt_vertex *vertices; stbtt_vertex *vertices;
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
stbtt__bitmap gbm; stbtt__bitmap gbm;
stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,0,0); stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
gbm.pixels = output; gbm.pixels = output;
gbm.w = out_w; gbm.w = out_w;
gbm.h = out_h; gbm.h = out_h;
gbm.stride = out_stride; gbm.stride = out_stride;
if (gbm.w && gbm.h) if (gbm.w && gbm.h)
stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1, info->userdata); stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
STBTT_free(vertices, info->userdata); 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_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)
{
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_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) 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_GetGlyphBitmap(info, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,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) 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_MakeGlyphBitmap(info, output, out_w, out_h, out_stride, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint)); stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// bitmap baking // bitmap baking
// //
// This is SUPER-SHITTY packing to keep source code small // 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) extern 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 float pixel_height, // height of font in pixels
@ -1638,8 +1895,8 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde
q->y1 = round_y + b->y1 - b->y0 + d3d_bias; q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
q->s0 = b->x0 * ipw; q->s0 = b->x0 * ipw;
q->t0 = b->y0 * ipw; q->t0 = b->y0 * iph;
q->s1 = b->x1 * iph; q->s1 = b->x1 * ipw;
q->t1 = b->y1 * iph; q->t1 = b->y1 * iph;
*xpos += b->xadvance; *xpos += b->xadvance;
@ -1651,7 +1908,7 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde
// //
// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2)
{ {
stbtt_int32 i=0; stbtt_int32 i=0;
@ -1692,12 +1949,12 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, s
int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
{ {
return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, 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 // returns results in whatever encoding you request... but note that 2-byte encodings
// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
{ {
stbtt_int32 i,count,stringOffset; stbtt_int32 i,count,stringOffset;
stbtt_uint8 *fc = font->data; stbtt_uint8 *fc = font->data;
@ -1712,7 +1969,7 @@ char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platf
if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
&& languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
*length = ttUSHORT(fc+loc+8); *length = ttUSHORT(fc+loc+8);
return (char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
} }
} }
return NULL; return NULL;
@ -1765,7 +2022,7 @@ static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name,
static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
{ {
stbtt_int32 nlen = STBTT_strlen((char *) name); stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
stbtt_uint32 nm,hd; stbtt_uint32 nm,hd;
if (!stbtt__isfont(fc+offset)) return 0; if (!stbtt__isfont(fc+offset)) return 0;

View File

@ -174,8 +174,12 @@ bool InputGeom::load(rcContext* ctx, const char* filePath)
fclose(fp); fclose(fp);
return false; return false;
} }
fread(buf, bufSize, 1, fp); size_t readLen = fread(buf, bufSize, 1, fp);
fclose(fp); fclose(fp);
if (readLen != 1)
{
return false;
}
m_offMeshConCount = 0; m_offMeshConCount = 0;
m_volumeCount = 0; m_volumeCount = 0;

View File

@ -78,7 +78,6 @@ void rcMeshLoaderObj::addTriangle(int a, int b, int c, int& cap)
static char* parseRow(char* buf, char* bufEnd, char* row, int len) static char* parseRow(char* buf, char* bufEnd, char* row, int len)
{ {
bool cont = false;
bool start = true; bool start = true;
bool done = false; bool done = false;
int n = 0; int n = 0;
@ -90,7 +89,6 @@ static char* parseRow(char* buf, char* bufEnd, char* row, int len)
switch (c) switch (c)
{ {
case '\\': case '\\':
cont = true; // multirow
break; break;
case '\n': case '\n':
if (start) break; if (start) break;
@ -103,7 +101,6 @@ static char* parseRow(char* buf, char* bufEnd, char* row, int len)
if (start) break; if (start) break;
default: default:
start = false; start = false;
cont = false;
row[n++] = c; row[n++] = c;
if (n >= len-1) if (n >= len-1)
done = true; done = true;
@ -153,9 +150,14 @@ bool rcMeshLoaderObj::load(const char* filename)
fclose(fp); fclose(fp);
return false; return false;
} }
fread(buf, bufSize, 1, fp); size_t readLen = fread(buf, bufSize, 1, fp);
fclose(fp); fclose(fp);
if (readLen != 1)
{
return false;
}
char* src = buf; char* src = buf;
char* srcEnd = buf + bufSize; char* srcEnd = buf + bufSize;
char row[512]; char row[512];

View File

@ -312,8 +312,8 @@ bool FileIO::write(const void* ptr, const size_t size)
bool FileIO::read(void* ptr, const size_t size) bool FileIO::read(void* ptr, const size_t size)
{ {
if (!m_fp || m_mode != 2) return false; if (!m_fp || m_mode != 2) return false;
fread(ptr, size, 1, m_fp); size_t readLen = fread(ptr, size, 1, m_fp);
return true; return readLen == 1;
} }

View File

@ -285,7 +285,12 @@ dtNavMesh* Sample_TileMesh::loadAll(const char* path)
// Read header. // Read header.
NavMeshSetHeader header; NavMeshSetHeader header;
fread(&header, sizeof(NavMeshSetHeader), 1, fp); size_t readLen = fread(&header, sizeof(NavMeshSetHeader), 1, fp);
if (readLen != 1)
{
fclose(fp);
return 0;
}
if (header.magic != NAVMESHSET_MAGIC) if (header.magic != NAVMESHSET_MAGIC)
{ {
fclose(fp); fclose(fp);
@ -314,14 +319,19 @@ dtNavMesh* Sample_TileMesh::loadAll(const char* path)
for (int i = 0; i < header.numTiles; ++i) for (int i = 0; i < header.numTiles; ++i)
{ {
NavMeshTileHeader tileHeader; NavMeshTileHeader tileHeader;
fread(&tileHeader, sizeof(tileHeader), 1, fp); readLen = fread(&tileHeader, sizeof(tileHeader), 1, fp);
if (readLen != 1)
return 0;
if (!tileHeader.tileRef || !tileHeader.dataSize) if (!tileHeader.tileRef || !tileHeader.dataSize)
break; break;
unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM); unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM);
if (!data) break; if (!data) break;
memset(data, 0, tileHeader.dataSize); memset(data, 0, tileHeader.dataSize);
fread(data, tileHeader.dataSize, 1, fp); readLen = fread(data, tileHeader.dataSize, 1, fp);
if (readLen != 1)
return 0;
mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0); mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0);
} }

View File

@ -106,8 +106,12 @@ bool TestCase::load(const char* filePath)
fclose(fp); fclose(fp);
return false; return false;
} }
fread(buf, bufSize, 1, fp); size_t readLen = fread(buf, bufSize, 1, fp);
fclose(fp); fclose(fp);
if (readLen != 1)
{
return false;
}
char* src = buf; char* src = buf;
char* srcEnd = buf + bufSize; char* srcEnd = buf + bufSize;

View File

@ -247,7 +247,7 @@ bool imguiRenderGLInit(const char* fontpath)
FILE* fp = fopen(fontpath, "rb"); FILE* fp = fopen(fontpath, "rb");
if (!fp) return false; if (!fp) return false;
fseek(fp, 0, SEEK_END); fseek(fp, 0, SEEK_END);
int size = ftell(fp); size_t size = ftell(fp);
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
unsigned char* ttfBuffer = (unsigned char*)malloc(size); unsigned char* ttfBuffer = (unsigned char*)malloc(size);
@ -257,8 +257,13 @@ bool imguiRenderGLInit(const char* fontpath)
return false; return false;
} }
fread(ttfBuffer, 1, size, fp); size_t readLen = fread(ttfBuffer, 1, size, fp);
fclose(fp); fclose(fp);
if (readLen != size)
{
return false;
}
fp = 0; fp = 0;
unsigned char* bmap = (unsigned char*)malloc(512*512); unsigned char* bmap = (unsigned char*)malloc(512*512);