ltkx

GUI toolkit for X11 (old)
git clone git://lumidify.org/ltkx.git (fast, but not encrypted)
git clone https://lumidify.org/ltkx.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltkx.git (over tor)
Log | Files | Refs | README | LICENSE

stb_truetype.c (142677B)


      1 // stb_truetype.h - v1.24 - public domain
      2 // authored from 2009-2020 by Sean Barrett / RAD Game Tools
      3 //
      4 // =======================================================================
      5 //
      6 //    NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
      7 //
      8 // This library does no range checking of the offsets found in the file,
      9 // meaning an attacker can use it to read arbitrary memory.
     10 //
     11 // =======================================================================
     12 
     13 #include "stb_truetype.h"
     14 
     15 typedef unsigned char   stbtt_uint8;
     16 typedef signed   char   stbtt_int8;
     17 typedef unsigned short  stbtt_uint16;
     18 typedef signed   short  stbtt_int16;
     19 typedef unsigned int    stbtt_uint32;
     20 typedef signed   int    stbtt_int32;
     21 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
     22 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
     23 #include <math.h>
     24 #define STBTT_ifloor(x)   ((int) floor(x))
     25 #define STBTT_iceil(x)    ((int) ceil(x))
     26 #include <math.h>
     27 #define STBTT_sqrt(x)      sqrt(x)
     28 #define STBTT_pow(x,y)     pow(x,y)
     29 #include <math.h>
     30 #define STBTT_fmod(x,y)    fmod(x,y)
     31 #include <math.h>
     32 #define STBTT_cos(x)       cos(x)
     33 #define STBTT_acos(x)      acos(x)
     34 #include <math.h>
     35 #define STBTT_fabs(x)      fabs(x)
     36 #include <stdlib.h>
     37 #define STBTT_malloc(x,u)  ((void)(u),malloc(x))
     38 #define STBTT_free(x,u)    ((void)(u),free(x))
     39 #include <assert.h>
     40 #define STBTT_assert(x)    assert(x)
     41 #include <string.h>
     42 #define STBTT_strlen(x)    strlen(x)
     43 #include <string.h>
     44 #define STBTT_memcpy       memcpy
     45 #define STBTT_memset       memset
     46 
     47 ///////////////////////////////////////////////////////////////////////////////
     48 ///////////////////////////////////////////////////////////////////////////////
     49 ////
     50 ////   IMPLEMENTATION
     51 ////
     52 ////
     53 
     54 #ifndef STBTT_MAX_OVERSAMPLE
     55 #define STBTT_MAX_OVERSAMPLE   8
     56 #endif
     57 
     58 #if STBTT_MAX_OVERSAMPLE > 255
     59 #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
     60 #endif
     61 
     62 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
     63 
     64 #ifndef STBTT_RASTERIZER_VERSION
     65 #define STBTT_RASTERIZER_VERSION 2
     66 #endif
     67 
     68 #ifdef _MSC_VER
     69 #define STBTT__NOTUSED(v)  (void)(v)
     70 #else
     71 #define STBTT__NOTUSED(v)  (void)sizeof(v)
     72 #endif
     73 
     74 //////////////////////////////////////////////////////////////////////////
     75 //
     76 // stbtt__buf helpers to parse data from file
     77 //
     78 
     79 static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
     80 {
     81    if (b->cursor >= b->size)
     82       return 0;
     83    return b->data[b->cursor++];
     84 }
     85 
     86 static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
     87 {
     88    if (b->cursor >= b->size)
     89       return 0;
     90    return b->data[b->cursor];
     91 }
     92 
     93 static void stbtt__buf_seek(stbtt__buf *b, int o)
     94 {
     95    STBTT_assert(!(o > b->size || o < 0));
     96    b->cursor = (o > b->size || o < 0) ? b->size : o;
     97 }
     98 
     99 static void stbtt__buf_skip(stbtt__buf *b, int o)
    100 {
    101    stbtt__buf_seek(b, b->cursor + o);
    102 }
    103 
    104 static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
    105 {
    106    stbtt_uint32 v = 0;
    107    int i;
    108    STBTT_assert(n >= 1 && n <= 4);
    109    for (i = 0; i < n; i++)
    110       v = (v << 8) | stbtt__buf_get8(b);
    111    return v;
    112 }
    113 
    114 static stbtt__buf stbtt__new_buf(const void *p, size_t size)
    115 {
    116    stbtt__buf r;
    117    STBTT_assert(size < 0x40000000);
    118    r.data = (stbtt_uint8*) p;
    119    r.size = (int) size;
    120    r.cursor = 0;
    121    return r;
    122 }
    123 
    124 #define stbtt__buf_get16(b)  stbtt__buf_get((b), 2)
    125 #define stbtt__buf_get32(b)  stbtt__buf_get((b), 4)
    126 
    127 static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
    128 {
    129    stbtt__buf r = stbtt__new_buf(NULL, 0);
    130    if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
    131    r.data = b->data + o;
    132    r.size = s;
    133    return r;
    134 }
    135 
    136 static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
    137 {
    138    int count, start, offsize;
    139    start = b->cursor;
    140    count = stbtt__buf_get16(b);
    141    if (count) {
    142       offsize = stbtt__buf_get8(b);
    143       STBTT_assert(offsize >= 1 && offsize <= 4);
    144       stbtt__buf_skip(b, offsize * count);
    145       stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
    146    }
    147    return stbtt__buf_range(b, start, b->cursor - start);
    148 }
    149 
    150 static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
    151 {
    152    int b0 = stbtt__buf_get8(b);
    153    if (b0 >= 32 && b0 <= 246)       return b0 - 139;
    154    else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
    155    else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
    156    else if (b0 == 28)               return stbtt__buf_get16(b);
    157    else if (b0 == 29)               return stbtt__buf_get32(b);
    158    STBTT_assert(0);
    159    return 0;
    160 }
    161 
    162 static void stbtt__cff_skip_operand(stbtt__buf *b) {
    163    int v, b0 = stbtt__buf_peek8(b);
    164    STBTT_assert(b0 >= 28);
    165    if (b0 == 30) {
    166       stbtt__buf_skip(b, 1);
    167       while (b->cursor < b->size) {
    168          v = stbtt__buf_get8(b);
    169          if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
    170             break;
    171       }
    172    } else {
    173       stbtt__cff_int(b);
    174    }
    175 }
    176 
    177 static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
    178 {
    179    stbtt__buf_seek(b, 0);
    180    while (b->cursor < b->size) {
    181       int start = b->cursor, end, op;
    182       while (stbtt__buf_peek8(b) >= 28)
    183          stbtt__cff_skip_operand(b);
    184       end = b->cursor;
    185       op = stbtt__buf_get8(b);
    186       if (op == 12)  op = stbtt__buf_get8(b) | 0x100;
    187       if (op == key) return stbtt__buf_range(b, start, end-start);
    188    }
    189    return stbtt__buf_range(b, 0, 0);
    190 }
    191 
    192 static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
    193 {
    194    int i;
    195    stbtt__buf operands = stbtt__dict_get(b, key);
    196    for (i = 0; i < outcount && operands.cursor < operands.size; i++)
    197       out[i] = stbtt__cff_int(&operands);
    198 }
    199 
    200 static int stbtt__cff_index_count(stbtt__buf *b)
    201 {
    202    stbtt__buf_seek(b, 0);
    203    return stbtt__buf_get16(b);
    204 }
    205 
    206 static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
    207 {
    208    int count, offsize, start, end;
    209    stbtt__buf_seek(&b, 0);
    210    count = stbtt__buf_get16(&b);
    211    offsize = stbtt__buf_get8(&b);
    212    STBTT_assert(i >= 0 && i < count);
    213    STBTT_assert(offsize >= 1 && offsize <= 4);
    214    stbtt__buf_skip(&b, i*offsize);
    215    start = stbtt__buf_get(&b, offsize);
    216    end = stbtt__buf_get(&b, offsize);
    217    return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
    218 }
    219 
    220 //////////////////////////////////////////////////////////////////////////
    221 //
    222 // accessors to parse data from file
    223 //
    224 
    225 // on platforms that don't allow misaligned reads, if we want to allow
    226 // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
    227 
    228 #define ttBYTE(p)     (* (stbtt_uint8 *) (p))
    229 #define ttCHAR(p)     (* (stbtt_int8 *) (p))
    230 #define ttFixed(p)    ttLONG(p)
    231 
    232 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
    233 static stbtt_int16 ttSHORT(stbtt_uint8 *p)   { return p[0]*256 + p[1]; }
    234 static stbtt_uint32 ttULONG(stbtt_uint8 *p)  { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
    235 static stbtt_int32 ttLONG(stbtt_uint8 *p)    { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
    236 
    237 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
    238 #define stbtt_tag(p,str)           stbtt_tag4(p,str[0],str[1],str[2],str[3])
    239 
    240 static int stbtt__isfont(stbtt_uint8 *font)
    241 {
    242    // check the version number
    243    if (stbtt_tag4(font, '1',0,0,0))  return 1; // TrueType 1
    244    if (stbtt_tag(font, "typ1"))   return 1; // TrueType with type 1 font -- we don't support this!
    245    if (stbtt_tag(font, "OTTO"))   return 1; // OpenType with CFF
    246    if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
    247    if (stbtt_tag(font, "true"))   return 1; // Apple specification for TrueType fonts
    248    return 0;
    249 }
    250 
    251 // @OPTIMIZE: binary search
    252 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
    253 {
    254    stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
    255    stbtt_uint32 tabledir = fontstart + 12;
    256    stbtt_int32 i;
    257    for (i=0; i < num_tables; ++i) {
    258       stbtt_uint32 loc = tabledir + 16*i;
    259       if (stbtt_tag(data+loc+0, tag))
    260          return ttULONG(data+loc+8);
    261    }
    262    return 0;
    263 }
    264 
    265 static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
    266 {
    267    // if it's just a font, there's only one valid index
    268    if (stbtt__isfont(font_collection))
    269       return index == 0 ? 0 : -1;
    270 
    271    // check if it's a TTC
    272    if (stbtt_tag(font_collection, "ttcf")) {
    273       // version 1?
    274       if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
    275          stbtt_int32 n = ttLONG(font_collection+8);
    276          if (index >= n)
    277             return -1;
    278          return ttULONG(font_collection+12+index*4);
    279       }
    280    }
    281    return -1;
    282 }
    283 
    284 static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
    285 {
    286    // if it's just a font, there's only one valid font
    287    if (stbtt__isfont(font_collection))
    288       return 1;
    289 
    290    // check if it's a TTC
    291    if (stbtt_tag(font_collection, "ttcf")) {
    292       // version 1?
    293       if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
    294          return ttLONG(font_collection+8);
    295       }
    296    }
    297    return 0;
    298 }
    299 
    300 static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
    301 {
    302    stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
    303    stbtt__buf pdict;
    304    stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
    305    if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
    306    pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
    307    stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
    308    if (!subrsoff) return stbtt__new_buf(NULL, 0);
    309    stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
    310    return stbtt__cff_get_index(&cff);
    311 }
    312 
    313 // since most people won't use this, find this table the first time it's needed
    314 static int stbtt__get_svg(stbtt_fontinfo *info)
    315 {
    316    stbtt_uint32 t;
    317    if (info->svg < 0) {
    318       t = stbtt__find_table(info->data, info->fontstart, "SVG ");
    319       if (t) {
    320          stbtt_uint32 offset = ttULONG(info->data + t + 2);
    321          info->svg = t + offset;
    322       } else {
    323          info->svg = 0;
    324       }
    325    }
    326    return info->svg;
    327 }
    328 
    329 static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
    330 {
    331    stbtt_uint32 cmap, t;
    332    stbtt_int32 i,numTables;
    333 
    334    info->data = data;
    335    info->fontstart = fontstart;
    336    info->cff = stbtt__new_buf(NULL, 0);
    337 
    338    cmap = stbtt__find_table(data, fontstart, "cmap");       // required
    339    info->loca = stbtt__find_table(data, fontstart, "loca"); // required
    340    info->head = stbtt__find_table(data, fontstart, "head"); // required
    341    info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
    342    info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
    343    info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
    344    info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
    345    info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
    346 
    347    if (!cmap || !info->head || !info->hhea || !info->hmtx)
    348       return 0;
    349    if (info->glyf) {
    350       // required for truetype
    351       if (!info->loca) return 0;
    352    } else {
    353       // initialization for CFF / Type2 fonts (OTF)
    354       stbtt__buf b, topdict, topdictidx;
    355       stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
    356       stbtt_uint32 cff;
    357 
    358       cff = stbtt__find_table(data, fontstart, "CFF ");
    359       if (!cff) return 0;
    360 
    361       info->fontdicts = stbtt__new_buf(NULL, 0);
    362       info->fdselect = stbtt__new_buf(NULL, 0);
    363 
    364       // @TODO this should use size from table (not 512MB)
    365       info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
    366       b = info->cff;
    367 
    368       // read the header
    369       stbtt__buf_skip(&b, 2);
    370       stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
    371 
    372       // @TODO the name INDEX could list multiple fonts,
    373       // but we just use the first one.
    374       stbtt__cff_get_index(&b);  // name INDEX
    375       topdictidx = stbtt__cff_get_index(&b);
    376       topdict = stbtt__cff_index_get(topdictidx, 0);
    377       stbtt__cff_get_index(&b);  // string INDEX
    378       info->gsubrs = stbtt__cff_get_index(&b);
    379 
    380       stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
    381       stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
    382       stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
    383       stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
    384       info->subrs = stbtt__get_subrs(b, topdict);
    385 
    386       // we only support Type 2 charstrings
    387       if (cstype != 2) return 0;
    388       if (charstrings == 0) return 0;
    389 
    390       if (fdarrayoff) {
    391          // looks like a CID font
    392          if (!fdselectoff) return 0;
    393          stbtt__buf_seek(&b, fdarrayoff);
    394          info->fontdicts = stbtt__cff_get_index(&b);
    395          info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
    396       }
    397 
    398       stbtt__buf_seek(&b, charstrings);
    399       info->charstrings = stbtt__cff_get_index(&b);
    400    }
    401 
    402    t = stbtt__find_table(data, fontstart, "maxp");
    403    if (t)
    404       info->numGlyphs = ttUSHORT(data+t+4);
    405    else
    406       info->numGlyphs = 0xffff;
    407 
    408    info->svg = -1;
    409 
    410    // find a cmap encoding table we understand *now* to avoid searching
    411    // later. (todo: could make this installable)
    412    // the same regardless of glyph.
    413    numTables = ttUSHORT(data + cmap + 2);
    414    info->index_map = 0;
    415    for (i=0; i < numTables; ++i) {
    416       stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
    417       // find an encoding we understand:
    418       switch(ttUSHORT(data+encoding_record)) {
    419          case STBTT_PLATFORM_ID_MICROSOFT:
    420             switch (ttUSHORT(data+encoding_record+2)) {
    421                case STBTT_MS_EID_UNICODE_BMP:
    422                case STBTT_MS_EID_UNICODE_FULL:
    423                   // MS/Unicode
    424                   info->index_map = cmap + ttULONG(data+encoding_record+4);
    425                   break;
    426             }
    427             break;
    428         case STBTT_PLATFORM_ID_UNICODE:
    429             // Mac/iOS has these
    430             // all the encodingIDs are unicode, so we don't bother to check it
    431             info->index_map = cmap + ttULONG(data+encoding_record+4);
    432             break;
    433       }
    434    }
    435    if (info->index_map == 0)
    436       return 0;
    437 
    438    info->indexToLocFormat = ttUSHORT(data+info->head + 50);
    439    return 1;
    440 }
    441 
    442 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
    443 {
    444    stbtt_uint8 *data = info->data;
    445    stbtt_uint32 index_map = info->index_map;
    446 
    447    stbtt_uint16 format = ttUSHORT(data + index_map + 0);
    448    if (format == 0) { // apple byte encoding
    449       stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
    450       if (unicode_codepoint < bytes-6)
    451          return ttBYTE(data + index_map + 6 + unicode_codepoint);
    452       return 0;
    453    } else if (format == 6) {
    454       stbtt_uint32 first = ttUSHORT(data + index_map + 6);
    455       stbtt_uint32 count = ttUSHORT(data + index_map + 8);
    456       if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
    457          return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
    458       return 0;
    459    } else if (format == 2) {
    460       STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
    461       return 0;
    462    } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
    463       stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
    464       stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
    465       stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
    466       stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
    467 
    468       // do a binary search of the segments
    469       stbtt_uint32 endCount = index_map + 14;
    470       stbtt_uint32 search = endCount;
    471 
    472       if (unicode_codepoint > 0xffff)
    473          return 0;
    474 
    475       // they lie from endCount .. endCount + segCount
    476       // but searchRange is the nearest power of two, so...
    477       if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
    478          search += rangeShift*2;
    479 
    480       // now decrement to bias correctly to find smallest
    481       search -= 2;
    482       while (entrySelector) {
    483          stbtt_uint16 end;
    484          searchRange >>= 1;
    485          end = ttUSHORT(data + search + searchRange*2);
    486          if (unicode_codepoint > end)
    487             search += searchRange*2;
    488          --entrySelector;
    489       }
    490       search += 2;
    491 
    492       {
    493          stbtt_uint16 offset, start;
    494          stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
    495 
    496          STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
    497          start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
    498          if (unicode_codepoint < start)
    499             return 0;
    500 
    501          offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
    502          if (offset == 0)
    503             return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
    504 
    505          return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
    506       }
    507    } else if (format == 12 || format == 13) {
    508       stbtt_uint32 ngroups = ttULONG(data+index_map+12);
    509       stbtt_int32 low,high;
    510       low = 0; high = (stbtt_int32)ngroups;
    511       // Binary search the right group.
    512       while (low < high) {
    513          stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
    514          stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
    515          stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
    516          if ((stbtt_uint32) unicode_codepoint < start_char)
    517             high = mid;
    518          else if ((stbtt_uint32) unicode_codepoint > end_char)
    519             low = mid+1;
    520          else {
    521             stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
    522             if (format == 12)
    523                return start_glyph + unicode_codepoint-start_char;
    524             else // format == 13
    525                return start_glyph;
    526          }
    527       }
    528       return 0; // not found
    529    }
    530    // @TODO
    531    STBTT_assert(0);
    532    return 0;
    533 }
    534 
    535 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
    536 {
    537    return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
    538 }
    539 
    540 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
    541 {
    542    v->type = type;
    543    v->x = (stbtt_int16) x;
    544    v->y = (stbtt_int16) y;
    545    v->cx = (stbtt_int16) cx;
    546    v->cy = (stbtt_int16) cy;
    547 }
    548 
    549 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
    550 {
    551    int g1,g2;
    552 
    553    STBTT_assert(!info->cff.size);
    554 
    555    if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
    556    if (info->indexToLocFormat >= 2)    return -1; // unknown index->glyph map format
    557 
    558    if (info->indexToLocFormat == 0) {
    559       g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
    560       g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
    561    } else {
    562       g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
    563       g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
    564    }
    565 
    566    return g1==g2 ? -1 : g1; // if length is 0, return -1
    567 }
    568 
    569 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
    570 
    571 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
    572 {
    573    if (info->cff.size) {
    574       stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
    575    } else {
    576       int g = stbtt__GetGlyfOffset(info, glyph_index);
    577       if (g < 0) return 0;
    578 
    579       if (x0) *x0 = ttSHORT(info->data + g + 2);
    580       if (y0) *y0 = ttSHORT(info->data + g + 4);
    581       if (x1) *x1 = ttSHORT(info->data + g + 6);
    582       if (y1) *y1 = ttSHORT(info->data + g + 8);
    583    }
    584    return 1;
    585 }
    586 
    587 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
    588 {
    589    return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
    590 }
    591 
    592 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
    593 {
    594    stbtt_int16 numberOfContours;
    595    int g;
    596    if (info->cff.size)
    597       return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
    598    g = stbtt__GetGlyfOffset(info, glyph_index);
    599    if (g < 0) return 1;
    600    numberOfContours = ttSHORT(info->data + g);
    601    return numberOfContours == 0;
    602 }
    603 
    604 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
    605     stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
    606 {
    607    if (start_off) {
    608       if (was_off)
    609          stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
    610       stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
    611    } else {
    612       if (was_off)
    613          stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
    614       else
    615          stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
    616    }
    617    return num_vertices;
    618 }
    619 
    620 static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
    621 {
    622    stbtt_int16 numberOfContours;
    623    stbtt_uint8 *endPtsOfContours;
    624    stbtt_uint8 *data = info->data;
    625    stbtt_vertex *vertices=0;
    626    int num_vertices=0;
    627    int g = stbtt__GetGlyfOffset(info, glyph_index);
    628 
    629    *pvertices = NULL;
    630 
    631    if (g < 0) return 0;
    632 
    633    numberOfContours = ttSHORT(data + g);
    634 
    635    if (numberOfContours > 0) {
    636       stbtt_uint8 flags=0,flagcount;
    637       stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
    638       stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
    639       stbtt_uint8 *points;
    640       endPtsOfContours = (data + g + 10);
    641       ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
    642       points = data + g + 10 + numberOfContours * 2 + 2 + ins;
    643 
    644       n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
    645 
    646       m = n + 2*numberOfContours;  // a loose bound on how many vertices we might need
    647       vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
    648       if (vertices == 0)
    649          return 0;
    650 
    651       next_move = 0;
    652       flagcount=0;
    653 
    654       // in first pass, we load uninterpreted data into the allocated array
    655       // above, shifted to the end of the array so we won't overwrite it when
    656       // we create our final data starting from the front
    657 
    658       off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
    659 
    660       // first load flags
    661 
    662       for (i=0; i < n; ++i) {
    663          if (flagcount == 0) {
    664             flags = *points++;
    665             if (flags & 8)
    666                flagcount = *points++;
    667          } else
    668             --flagcount;
    669          vertices[off+i].type = flags;
    670       }
    671 
    672       // now load x coordinates
    673       x=0;
    674       for (i=0; i < n; ++i) {
    675          flags = vertices[off+i].type;
    676          if (flags & 2) {
    677             stbtt_int16 dx = *points++;
    678             x += (flags & 16) ? dx : -dx; // ???
    679          } else {
    680             if (!(flags & 16)) {
    681                x = x + (stbtt_int16) (points[0]*256 + points[1]);
    682                points += 2;
    683             }
    684          }
    685          vertices[off+i].x = (stbtt_int16) x;
    686       }
    687 
    688       // now load y coordinates
    689       y=0;
    690       for (i=0; i < n; ++i) {
    691          flags = vertices[off+i].type;
    692          if (flags & 4) {
    693             stbtt_int16 dy = *points++;
    694             y += (flags & 32) ? dy : -dy; // ???
    695          } else {
    696             if (!(flags & 32)) {
    697                y = y + (stbtt_int16) (points[0]*256 + points[1]);
    698                points += 2;
    699             }
    700          }
    701          vertices[off+i].y = (stbtt_int16) y;
    702       }
    703 
    704       // now convert them to our format
    705       num_vertices=0;
    706       sx = sy = cx = cy = scx = scy = 0;
    707       for (i=0; i < n; ++i) {
    708          flags = vertices[off+i].type;
    709          x     = (stbtt_int16) vertices[off+i].x;
    710          y     = (stbtt_int16) vertices[off+i].y;
    711 
    712          if (next_move == i) {
    713             if (i != 0)
    714                num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
    715 
    716             // now start the new one
    717             start_off = !(flags & 1);
    718             if (start_off) {
    719                // if we start off with an off-curve point, then when we need to find a point on the curve
    720                // where we can start, and we need to save some state for when we wraparound.
    721                scx = x;
    722                scy = y;
    723                if (!(vertices[off+i+1].type & 1)) {
    724                   // next point is also a curve point, so interpolate an on-point curve
    725                   sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
    726                   sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
    727                } else {
    728                   // otherwise just use the next point as our start point
    729                   sx = (stbtt_int32) vertices[off+i+1].x;
    730                   sy = (stbtt_int32) vertices[off+i+1].y;
    731                   ++i; // we're using point i+1 as the starting point, so skip it
    732                }
    733             } else {
    734                sx = x;
    735                sy = y;
    736             }
    737             stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
    738             was_off = 0;
    739             next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
    740             ++j;
    741          } else {
    742             if (!(flags & 1)) { // if it's a curve
    743                if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
    744                   stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
    745                cx = x;
    746                cy = y;
    747                was_off = 1;
    748             } else {
    749                if (was_off)
    750                   stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
    751                else
    752                   stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
    753                was_off = 0;
    754             }
    755          }
    756       }
    757       num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
    758    } else if (numberOfContours < 0) {
    759       // Compound shapes.
    760       int more = 1;
    761       stbtt_uint8 *comp = data + g + 10;
    762       num_vertices = 0;
    763       vertices = 0;
    764       while (more) {
    765          stbtt_uint16 flags, gidx;
    766          int comp_num_verts = 0, i;
    767          stbtt_vertex *comp_verts = 0, *tmp = 0;
    768          float mtx[6] = {1,0,0,1,0,0}, m, n;
    769 
    770          flags = ttSHORT(comp); comp+=2;
    771          gidx = ttSHORT(comp); comp+=2;
    772 
    773          if (flags & 2) { // XY values
    774             if (flags & 1) { // shorts
    775                mtx[4] = ttSHORT(comp); comp+=2;
    776                mtx[5] = ttSHORT(comp); comp+=2;
    777             } else {
    778                mtx[4] = ttCHAR(comp); comp+=1;
    779                mtx[5] = ttCHAR(comp); comp+=1;
    780             }
    781          }
    782          else {
    783             // @TODO handle matching point
    784             STBTT_assert(0);
    785          }
    786          if (flags & (1<<3)) { // WE_HAVE_A_SCALE
    787             mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
    788             mtx[1] = mtx[2] = 0;
    789          } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
    790             mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
    791             mtx[1] = mtx[2] = 0;
    792             mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
    793          } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
    794             mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
    795             mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
    796             mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
    797             mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
    798          }
    799 
    800          // Find transformation scales.
    801          m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
    802          n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
    803 
    804          // Get indexed glyph.
    805          comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
    806          if (comp_num_verts > 0) {
    807             // Transform vertices.
    808             for (i = 0; i < comp_num_verts; ++i) {
    809                stbtt_vertex* v = &comp_verts[i];
    810                stbtt_vertex_type x,y;
    811                x=v->x; y=v->y;
    812                v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
    813                v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
    814                x=v->cx; y=v->cy;
    815                v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
    816                v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
    817             }
    818             // Append vertices.
    819             tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
    820             if (!tmp) {
    821                if (vertices) STBTT_free(vertices, info->userdata);
    822                if (comp_verts) STBTT_free(comp_verts, info->userdata);
    823                return 0;
    824             }
    825             if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
    826             STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
    827             if (vertices) STBTT_free(vertices, info->userdata);
    828             vertices = tmp;
    829             STBTT_free(comp_verts, info->userdata);
    830             num_vertices += comp_num_verts;
    831          }
    832          // More components ?
    833          more = flags & (1<<5);
    834       }
    835    } else {
    836       // numberOfCounters == 0, do nothing
    837    }
    838 
    839    *pvertices = vertices;
    840    return num_vertices;
    841 }
    842 
    843 typedef struct
    844 {
    845    int bounds;
    846    int started;
    847    float first_x, first_y;
    848    float x, y;
    849    stbtt_int32 min_x, max_x, min_y, max_y;
    850 
    851    stbtt_vertex *pvertices;
    852    int num_vertices;
    853 } stbtt__csctx;
    854 
    855 #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
    856 
    857 static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
    858 {
    859    if (x > c->max_x || !c->started) c->max_x = x;
    860    if (y > c->max_y || !c->started) c->max_y = y;
    861    if (x < c->min_x || !c->started) c->min_x = x;
    862    if (y < c->min_y || !c->started) c->min_y = y;
    863    c->started = 1;
    864 }
    865 
    866 static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
    867 {
    868    if (c->bounds) {
    869       stbtt__track_vertex(c, x, y);
    870       if (type == STBTT_vcubic) {
    871          stbtt__track_vertex(c, cx, cy);
    872          stbtt__track_vertex(c, cx1, cy1);
    873       }
    874    } else {
    875       stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
    876       c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
    877       c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
    878    }
    879    c->num_vertices++;
    880 }
    881 
    882 static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
    883 {
    884    if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
    885       stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
    886 }
    887 
    888 static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
    889 {
    890    stbtt__csctx_close_shape(ctx);
    891    ctx->first_x = ctx->x = ctx->x + dx;
    892    ctx->first_y = ctx->y = ctx->y + dy;
    893    stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
    894 }
    895 
    896 static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
    897 {
    898    ctx->x += dx;
    899    ctx->y += dy;
    900    stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
    901 }
    902 
    903 static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
    904 {
    905    float cx1 = ctx->x + dx1;
    906    float cy1 = ctx->y + dy1;
    907    float cx2 = cx1 + dx2;
    908    float cy2 = cy1 + dy2;
    909    ctx->x = cx2 + dx3;
    910    ctx->y = cy2 + dy3;
    911    stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
    912 }
    913 
    914 static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
    915 {
    916    int count = stbtt__cff_index_count(&idx);
    917    int bias = 107;
    918    if (count >= 33900)
    919       bias = 32768;
    920    else if (count >= 1240)
    921       bias = 1131;
    922    n += bias;
    923    if (n < 0 || n >= count)
    924       return stbtt__new_buf(NULL, 0);
    925    return stbtt__cff_index_get(idx, n);
    926 }
    927 
    928 static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
    929 {
    930    stbtt__buf fdselect = info->fdselect;
    931    int nranges, start, end, v, fmt, fdselector = -1, i;
    932 
    933    stbtt__buf_seek(&fdselect, 0);
    934    fmt = stbtt__buf_get8(&fdselect);
    935    if (fmt == 0) {
    936       // untested
    937       stbtt__buf_skip(&fdselect, glyph_index);
    938       fdselector = stbtt__buf_get8(&fdselect);
    939    } else if (fmt == 3) {
    940       nranges = stbtt__buf_get16(&fdselect);
    941       start = stbtt__buf_get16(&fdselect);
    942       for (i = 0; i < nranges; i++) {
    943          v = stbtt__buf_get8(&fdselect);
    944          end = stbtt__buf_get16(&fdselect);
    945          if (glyph_index >= start && glyph_index < end) {
    946             fdselector = v;
    947             break;
    948          }
    949          start = end;
    950       }
    951    }
    952    if (fdselector == -1) stbtt__new_buf(NULL, 0);
    953    return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
    954 }
    955 
    956 static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
    957 {
    958    int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
    959    int has_subrs = 0, clear_stack;
    960    float s[48];
    961    stbtt__buf subr_stack[10], subrs = info->subrs, b;
    962    float f;
    963 
    964 #define STBTT__CSERR(s) (0)
    965 
    966    // this currently ignores the initial width value, which isn't needed if we have hmtx
    967    b = stbtt__cff_index_get(info->charstrings, glyph_index);
    968    while (b.cursor < b.size) {
    969       i = 0;
    970       clear_stack = 1;
    971       b0 = stbtt__buf_get8(&b);
    972       switch (b0) {
    973       // @TODO implement hinting
    974       case 0x13: // hintmask
    975       case 0x14: // cntrmask
    976          if (in_header)
    977             maskbits += (sp / 2); // implicit "vstem"
    978          in_header = 0;
    979          stbtt__buf_skip(&b, (maskbits + 7) / 8);
    980          break;
    981 
    982       case 0x01: // hstem
    983       case 0x03: // vstem
    984       case 0x12: // hstemhm
    985       case 0x17: // vstemhm
    986          maskbits += (sp / 2);
    987          break;
    988 
    989       case 0x15: // rmoveto
    990          in_header = 0;
    991          if (sp < 2) return STBTT__CSERR("rmoveto stack");
    992          stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
    993          break;
    994       case 0x04: // vmoveto
    995          in_header = 0;
    996          if (sp < 1) return STBTT__CSERR("vmoveto stack");
    997          stbtt__csctx_rmove_to(c, 0, s[sp-1]);
    998          break;
    999       case 0x16: // hmoveto
   1000          in_header = 0;
   1001          if (sp < 1) return STBTT__CSERR("hmoveto stack");
   1002          stbtt__csctx_rmove_to(c, s[sp-1], 0);
   1003          break;
   1004 
   1005       case 0x05: // rlineto
   1006          if (sp < 2) return STBTT__CSERR("rlineto stack");
   1007          for (; i + 1 < sp; i += 2)
   1008             stbtt__csctx_rline_to(c, s[i], s[i+1]);
   1009          break;
   1010 
   1011       // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
   1012       // starting from a different place.
   1013 
   1014       case 0x07: // vlineto
   1015          if (sp < 1) return STBTT__CSERR("vlineto stack");
   1016          goto vlineto;
   1017       case 0x06: // hlineto
   1018          if (sp < 1) return STBTT__CSERR("hlineto stack");
   1019          for (;;) {
   1020             if (i >= sp) break;
   1021             stbtt__csctx_rline_to(c, s[i], 0);
   1022             i++;
   1023       vlineto:
   1024             if (i >= sp) break;
   1025             stbtt__csctx_rline_to(c, 0, s[i]);
   1026             i++;
   1027          }
   1028          break;
   1029 
   1030       case 0x1F: // hvcurveto
   1031          if (sp < 4) return STBTT__CSERR("hvcurveto stack");
   1032          goto hvcurveto;
   1033       case 0x1E: // vhcurveto
   1034          if (sp < 4) return STBTT__CSERR("vhcurveto stack");
   1035          for (;;) {
   1036             if (i + 3 >= sp) break;
   1037             stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
   1038             i += 4;
   1039       hvcurveto:
   1040             if (i + 3 >= sp) break;
   1041             stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
   1042             i += 4;
   1043          }
   1044          break;
   1045 
   1046       case 0x08: // rrcurveto
   1047          if (sp < 6) return STBTT__CSERR("rcurveline stack");
   1048          for (; i + 5 < sp; i += 6)
   1049             stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
   1050          break;
   1051 
   1052       case 0x18: // rcurveline
   1053          if (sp < 8) return STBTT__CSERR("rcurveline stack");
   1054          for (; i + 5 < sp - 2; i += 6)
   1055             stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
   1056          if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
   1057          stbtt__csctx_rline_to(c, s[i], s[i+1]);
   1058          break;
   1059 
   1060       case 0x19: // rlinecurve
   1061          if (sp < 8) return STBTT__CSERR("rlinecurve stack");
   1062          for (; i + 1 < sp - 6; i += 2)
   1063             stbtt__csctx_rline_to(c, s[i], s[i+1]);
   1064          if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
   1065          stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
   1066          break;
   1067 
   1068       case 0x1A: // vvcurveto
   1069       case 0x1B: // hhcurveto
   1070          if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
   1071          f = 0.0;
   1072          if (sp & 1) { f = s[i]; i++; }
   1073          for (; i + 3 < sp; i += 4) {
   1074             if (b0 == 0x1B)
   1075                stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
   1076             else
   1077                stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
   1078             f = 0.0;
   1079          }
   1080          break;
   1081 
   1082       case 0x0A: // callsubr
   1083          if (!has_subrs) {
   1084             if (info->fdselect.size)
   1085                subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
   1086             has_subrs = 1;
   1087          }
   1088          // fallthrough
   1089       case 0x1D: // callgsubr
   1090          if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
   1091          v = (int) s[--sp];
   1092          if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
   1093          subr_stack[subr_stack_height++] = b;
   1094          b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
   1095          if (b.size == 0) return STBTT__CSERR("subr not found");
   1096          b.cursor = 0;
   1097          clear_stack = 0;
   1098          break;
   1099 
   1100       case 0x0B: // return
   1101          if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
   1102          b = subr_stack[--subr_stack_height];
   1103          clear_stack = 0;
   1104          break;
   1105 
   1106       case 0x0E: // endchar
   1107          stbtt__csctx_close_shape(c);
   1108          return 1;
   1109 
   1110       case 0x0C: { // two-byte escape
   1111          float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
   1112          float dx, dy;
   1113          int b1 = stbtt__buf_get8(&b);
   1114          switch (b1) {
   1115          // @TODO These "flex" implementations ignore the flex-depth and resolution,
   1116          // and always draw beziers.
   1117          case 0x22: // hflex
   1118             if (sp < 7) return STBTT__CSERR("hflex stack");
   1119             dx1 = s[0];
   1120             dx2 = s[1];
   1121             dy2 = s[2];
   1122             dx3 = s[3];
   1123             dx4 = s[4];
   1124             dx5 = s[5];
   1125             dx6 = s[6];
   1126             stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
   1127             stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
   1128             break;
   1129 
   1130          case 0x23: // flex
   1131             if (sp < 13) return STBTT__CSERR("flex stack");
   1132             dx1 = s[0];
   1133             dy1 = s[1];
   1134             dx2 = s[2];
   1135             dy2 = s[3];
   1136             dx3 = s[4];
   1137             dy3 = s[5];
   1138             dx4 = s[6];
   1139             dy4 = s[7];
   1140             dx5 = s[8];
   1141             dy5 = s[9];
   1142             dx6 = s[10];
   1143             dy6 = s[11];
   1144             //fd is s[12]
   1145             stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
   1146             stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
   1147             break;
   1148 
   1149          case 0x24: // hflex1
   1150             if (sp < 9) return STBTT__CSERR("hflex1 stack");
   1151             dx1 = s[0];
   1152             dy1 = s[1];
   1153             dx2 = s[2];
   1154             dy2 = s[3];
   1155             dx3 = s[4];
   1156             dx4 = s[5];
   1157             dx5 = s[6];
   1158             dy5 = s[7];
   1159             dx6 = s[8];
   1160             stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
   1161             stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
   1162             break;
   1163 
   1164          case 0x25: // flex1
   1165             if (sp < 11) return STBTT__CSERR("flex1 stack");
   1166             dx1 = s[0];
   1167             dy1 = s[1];
   1168             dx2 = s[2];
   1169             dy2 = s[3];
   1170             dx3 = s[4];
   1171             dy3 = s[5];
   1172             dx4 = s[6];
   1173             dy4 = s[7];
   1174             dx5 = s[8];
   1175             dy5 = s[9];
   1176             dx6 = dy6 = s[10];
   1177             dx = dx1+dx2+dx3+dx4+dx5;
   1178             dy = dy1+dy2+dy3+dy4+dy5;
   1179             if (STBTT_fabs(dx) > STBTT_fabs(dy))
   1180                dy6 = -dy;
   1181             else
   1182                dx6 = -dx;
   1183             stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
   1184             stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
   1185             break;
   1186 
   1187          default:
   1188             return STBTT__CSERR("unimplemented");
   1189          }
   1190       } break;
   1191 
   1192       default:
   1193          if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
   1194             return STBTT__CSERR("reserved operator");
   1195 
   1196          // push immediate
   1197          if (b0 == 255) {
   1198             f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
   1199          } else {
   1200             stbtt__buf_skip(&b, -1);
   1201             f = (float)(stbtt_int16)stbtt__cff_int(&b);
   1202          }
   1203          if (sp >= 48) return STBTT__CSERR("push stack overflow");
   1204          s[sp++] = f;
   1205          clear_stack = 0;
   1206          break;
   1207       }
   1208       if (clear_stack) sp = 0;
   1209    }
   1210    return STBTT__CSERR("no endchar");
   1211 
   1212 #undef STBTT__CSERR
   1213 }
   1214 
   1215 static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
   1216 {
   1217    // runs the charstring twice, once to count and once to output (to avoid realloc)
   1218    stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
   1219    stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
   1220    if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
   1221       *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
   1222       output_ctx.pvertices = *pvertices;
   1223       if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
   1224          STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
   1225          return output_ctx.num_vertices;
   1226       }
   1227    }
   1228    *pvertices = NULL;
   1229    return 0;
   1230 }
   1231 
   1232 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
   1233 {
   1234    stbtt__csctx c = STBTT__CSCTX_INIT(1);
   1235    int r = stbtt__run_charstring(info, glyph_index, &c);
   1236    if (x0)  *x0 = r ? c.min_x : 0;
   1237    if (y0)  *y0 = r ? c.min_y : 0;
   1238    if (x1)  *x1 = r ? c.max_x : 0;
   1239    if (y1)  *y1 = r ? c.max_y : 0;
   1240    return r ? c.num_vertices : 0;
   1241 }
   1242 
   1243 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
   1244 {
   1245    if (!info->cff.size)
   1246       return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
   1247    else
   1248       return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
   1249 }
   1250 
   1251 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
   1252 {
   1253    stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
   1254    if (glyph_index < numOfLongHorMetrics) {
   1255       if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*glyph_index);
   1256       if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
   1257    } else {
   1258       if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
   1259       if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
   1260    }
   1261 }
   1262 
   1263 STBTT_DEF int  stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
   1264 {
   1265    stbtt_uint8 *data = info->data + info->kern;
   1266 
   1267    // we only look at the first table. it must be 'horizontal' and format 0.
   1268    if (!info->kern)
   1269       return 0;
   1270    if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
   1271       return 0;
   1272    if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
   1273       return 0;
   1274 
   1275    return ttUSHORT(data+10);
   1276 }
   1277 
   1278 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
   1279 {
   1280    stbtt_uint8 *data = info->data + info->kern;
   1281    int k, length;
   1282 
   1283    // we only look at the first table. it must be 'horizontal' and format 0.
   1284    if (!info->kern)
   1285       return 0;
   1286    if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
   1287       return 0;
   1288    if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
   1289       return 0;
   1290 
   1291    length = ttUSHORT(data+10);
   1292    if (table_length < length)
   1293       length = table_length;
   1294 
   1295    for (k = 0; k < length; k++)
   1296    {
   1297       table[k].glyph1 = ttUSHORT(data+18+(k*6));
   1298       table[k].glyph2 = ttUSHORT(data+20+(k*6));
   1299       table[k].advance = ttSHORT(data+22+(k*6));
   1300    }
   1301 
   1302    return length;
   1303 }
   1304 
   1305 static int  stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
   1306 {
   1307    stbtt_uint8 *data = info->data + info->kern;
   1308    stbtt_uint32 needle, straw;
   1309    int l, r, m;
   1310 
   1311    // we only look at the first table. it must be 'horizontal' and format 0.
   1312    if (!info->kern)
   1313       return 0;
   1314    if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
   1315       return 0;
   1316    if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
   1317       return 0;
   1318 
   1319    l = 0;
   1320    r = ttUSHORT(data+10) - 1;
   1321    needle = glyph1 << 16 | glyph2;
   1322    while (l <= r) {
   1323       m = (l + r) >> 1;
   1324       straw = ttULONG(data+18+(m*6)); // note: unaligned read
   1325       if (needle < straw)
   1326          r = m - 1;
   1327       else if (needle > straw)
   1328          l = m + 1;
   1329       else
   1330          return ttSHORT(data+22+(m*6));
   1331    }
   1332    return 0;
   1333 }
   1334 
   1335 static stbtt_int32  stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
   1336 {
   1337     stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
   1338     switch(coverageFormat) {
   1339         case 1: {
   1340             stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
   1341 
   1342             // Binary search.
   1343             stbtt_int32 l=0, r=glyphCount-1, m;
   1344             int straw, needle=glyph;
   1345             while (l <= r) {
   1346                 stbtt_uint8 *glyphArray = coverageTable + 4;
   1347                 stbtt_uint16 glyphID;
   1348                 m = (l + r) >> 1;
   1349                 glyphID = ttUSHORT(glyphArray + 2 * m);
   1350                 straw = glyphID;
   1351                 if (needle < straw)
   1352                     r = m - 1;
   1353                 else if (needle > straw)
   1354                     l = m + 1;
   1355                 else {
   1356                      return m;
   1357                 }
   1358             }
   1359         } break;
   1360 
   1361         case 2: {
   1362             stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
   1363             stbtt_uint8 *rangeArray = coverageTable + 4;
   1364 
   1365             // Binary search.
   1366             stbtt_int32 l=0, r=rangeCount-1, m;
   1367             int strawStart, strawEnd, needle=glyph;
   1368             while (l <= r) {
   1369                 stbtt_uint8 *rangeRecord;
   1370                 m = (l + r) >> 1;
   1371                 rangeRecord = rangeArray + 6 * m;
   1372                 strawStart = ttUSHORT(rangeRecord);
   1373                 strawEnd = ttUSHORT(rangeRecord + 2);
   1374                 if (needle < strawStart)
   1375                     r = m - 1;
   1376                 else if (needle > strawEnd)
   1377                     l = m + 1;
   1378                 else {
   1379                     stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
   1380                     return startCoverageIndex + glyph - strawStart;
   1381                 }
   1382             }
   1383         } break;
   1384 
   1385         default: {
   1386             // There are no other cases.
   1387             STBTT_assert(0);
   1388         } break;
   1389     }
   1390 
   1391     return -1;
   1392 }
   1393 
   1394 static stbtt_int32  stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
   1395 {
   1396     stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
   1397     switch(classDefFormat)
   1398     {
   1399         case 1: {
   1400             stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
   1401             stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
   1402             stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
   1403 
   1404             if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
   1405                 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
   1406 
   1407             classDefTable = classDef1ValueArray + 2 * glyphCount;
   1408         } break;
   1409 
   1410         case 2: {
   1411             stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
   1412             stbtt_uint8 *classRangeRecords = classDefTable + 4;
   1413 
   1414             // Binary search.
   1415             stbtt_int32 l=0, r=classRangeCount-1, m;
   1416             int strawStart, strawEnd, needle=glyph;
   1417             while (l <= r) {
   1418                 stbtt_uint8 *classRangeRecord;
   1419                 m = (l + r) >> 1;
   1420                 classRangeRecord = classRangeRecords + 6 * m;
   1421                 strawStart = ttUSHORT(classRangeRecord);
   1422                 strawEnd = ttUSHORT(classRangeRecord + 2);
   1423                 if (needle < strawStart)
   1424                     r = m - 1;
   1425                 else if (needle > strawEnd)
   1426                     l = m + 1;
   1427                 else
   1428                     return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
   1429             }
   1430 
   1431             classDefTable = classRangeRecords + 6 * classRangeCount;
   1432         } break;
   1433 
   1434         default: {
   1435             // There are no other cases.
   1436             STBTT_assert(0);
   1437         } break;
   1438     }
   1439 
   1440     return -1;
   1441 }
   1442 
   1443 // Define to STBTT_assert(x) if you want to break on unimplemented formats.
   1444 #define STBTT_GPOS_TODO_assert(x)
   1445 
   1446 static stbtt_int32  stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
   1447 {
   1448     stbtt_uint16 lookupListOffset;
   1449     stbtt_uint8 *lookupList;
   1450     stbtt_uint16 lookupCount;
   1451     stbtt_uint8 *data;
   1452     stbtt_int32 i;
   1453 
   1454     if (!info->gpos) return 0;
   1455 
   1456     data = info->data + info->gpos;
   1457 
   1458     if (ttUSHORT(data+0) != 1) return 0; // Major version 1
   1459     if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
   1460 
   1461     lookupListOffset = ttUSHORT(data+8);
   1462     lookupList = data + lookupListOffset;
   1463     lookupCount = ttUSHORT(lookupList);
   1464 
   1465     for (i=0; i<lookupCount; ++i) {
   1466         stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
   1467         stbtt_uint8 *lookupTable = lookupList + lookupOffset;
   1468 
   1469         stbtt_uint16 lookupType = ttUSHORT(lookupTable);
   1470         stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
   1471         stbtt_uint8 *subTableOffsets = lookupTable + 6;
   1472         switch(lookupType) {
   1473             case 2: { // Pair Adjustment Positioning Subtable
   1474                 stbtt_int32 sti;
   1475                 for (sti=0; sti<subTableCount; sti++) {
   1476                     stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
   1477                     stbtt_uint8 *table = lookupTable + subtableOffset;
   1478                     stbtt_uint16 posFormat = ttUSHORT(table);
   1479                     stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
   1480                     stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
   1481                     if (coverageIndex == -1) continue;
   1482 
   1483                     switch (posFormat) {
   1484                         case 1: {
   1485                             stbtt_int32 l, r, m;
   1486                             int straw, needle;
   1487                             stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
   1488                             stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
   1489                             stbtt_int32 valueRecordPairSizeInBytes = 2;
   1490                             stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
   1491                             stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
   1492                             stbtt_uint8 *pairValueTable = table + pairPosOffset;
   1493                             stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
   1494                             stbtt_uint8 *pairValueArray = pairValueTable + 2;
   1495                             // TODO: Support more formats.
   1496                             STBTT_GPOS_TODO_assert(valueFormat1 == 4);
   1497                             if (valueFormat1 != 4) return 0;
   1498                             STBTT_GPOS_TODO_assert(valueFormat2 == 0);
   1499                             if (valueFormat2 != 0) return 0;
   1500 
   1501                             STBTT_assert(coverageIndex < pairSetCount);
   1502                             STBTT__NOTUSED(pairSetCount);
   1503 
   1504                             needle=glyph2;
   1505                             r=pairValueCount-1;
   1506                             l=0;
   1507 
   1508                             // Binary search.
   1509                             while (l <= r) {
   1510                                 stbtt_uint16 secondGlyph;
   1511                                 stbtt_uint8 *pairValue;
   1512                                 m = (l + r) >> 1;
   1513                                 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
   1514                                 secondGlyph = ttUSHORT(pairValue);
   1515                                 straw = secondGlyph;
   1516                                 if (needle < straw)
   1517                                     r = m - 1;
   1518                                 else if (needle > straw)
   1519                                     l = m + 1;
   1520                                 else {
   1521                                     stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
   1522                                     return xAdvance;
   1523                                 }
   1524                             }
   1525                         } break;
   1526 
   1527                         case 2: {
   1528                             stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
   1529                             stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
   1530 
   1531                             stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
   1532                             stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
   1533                             int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
   1534                             int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
   1535 
   1536                             stbtt_uint16 class1Count = ttUSHORT(table + 12);
   1537                             stbtt_uint16 class2Count = ttUSHORT(table + 14);
   1538                             STBTT_assert(glyph1class < class1Count);
   1539                             STBTT_assert(glyph2class < class2Count);
   1540 
   1541                             // TODO: Support more formats.
   1542                             STBTT_GPOS_TODO_assert(valueFormat1 == 4);
   1543                             if (valueFormat1 != 4) return 0;
   1544                             STBTT_GPOS_TODO_assert(valueFormat2 == 0);
   1545                             if (valueFormat2 != 0) return 0;
   1546 
   1547                             if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
   1548                                 stbtt_uint8 *class1Records = table + 16;
   1549                                 stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
   1550                                 stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
   1551                                 return xAdvance;
   1552                             }
   1553                         } break;
   1554 
   1555                         default: {
   1556                             // There are no other cases.
   1557                             STBTT_assert(0);
   1558                             break;
   1559                         };
   1560                     }
   1561                 }
   1562                 break;
   1563             };
   1564 
   1565             default:
   1566                 // TODO: Implement other stuff.
   1567                 break;
   1568         }
   1569     }
   1570 
   1571     return 0;
   1572 }
   1573 
   1574 STBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
   1575 {
   1576    int xAdvance = 0;
   1577 
   1578    if (info->gpos)
   1579       xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
   1580    else if (info->kern)
   1581       xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
   1582 
   1583    return xAdvance;
   1584 }
   1585 
   1586 STBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
   1587 {
   1588    if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
   1589       return 0;
   1590    return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
   1591 }
   1592 
   1593 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
   1594 {
   1595    stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
   1596 }
   1597 
   1598 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
   1599 {
   1600    if (ascent ) *ascent  = ttSHORT(info->data+info->hhea + 4);
   1601    if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
   1602    if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
   1603 }
   1604 
   1605 STBTT_DEF int  stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
   1606 {
   1607    int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
   1608    if (!tab)
   1609       return 0;
   1610    if (typoAscent ) *typoAscent  = ttSHORT(info->data+tab + 68);
   1611    if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
   1612    if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
   1613    return 1;
   1614 }
   1615 
   1616 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
   1617 {
   1618    *x0 = ttSHORT(info->data + info->head + 36);
   1619    *y0 = ttSHORT(info->data + info->head + 38);
   1620    *x1 = ttSHORT(info->data + info->head + 40);
   1621    *y1 = ttSHORT(info->data + info->head + 42);
   1622 }
   1623 
   1624 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
   1625 {
   1626    int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
   1627    return (float) height / fheight;
   1628 }
   1629 
   1630 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
   1631 {
   1632    int unitsPerEm = ttUSHORT(info->data + info->head + 18);
   1633    return pixels / unitsPerEm;
   1634 }
   1635 
   1636 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
   1637 {
   1638    STBTT_free(v, info->userdata);
   1639 }
   1640 
   1641 STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
   1642 {
   1643    int i;
   1644    stbtt_uint8 *data = info->data;
   1645    stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
   1646 
   1647    int numEntries = ttUSHORT(svg_doc_list);
   1648    stbtt_uint8 *svg_docs = svg_doc_list + 2;
   1649 
   1650    for(i=0; i<numEntries; i++) {
   1651       stbtt_uint8 *svg_doc = svg_docs + (12 * i);
   1652       if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
   1653          return svg_doc;
   1654    }
   1655    return 0;
   1656 }
   1657 
   1658 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
   1659 {
   1660    stbtt_uint8 *data = info->data;
   1661    stbtt_uint8 *svg_doc;
   1662 
   1663    if (info->svg == 0)
   1664       return 0;
   1665 
   1666    svg_doc = stbtt_FindSVGDoc(info, gl);
   1667    if (svg_doc != NULL) {
   1668       *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
   1669       return ttULONG(svg_doc + 8);
   1670    } else {
   1671       return 0;
   1672    }
   1673 }
   1674 
   1675 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
   1676 {
   1677    return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
   1678 }
   1679 
   1680 //////////////////////////////////////////////////////////////////////////////
   1681 //
   1682 // antialiasing software rasterizer
   1683 //
   1684 
   1685 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)
   1686 {
   1687    int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
   1688    if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
   1689       // e.g. space character
   1690       if (ix0) *ix0 = 0;
   1691       if (iy0) *iy0 = 0;
   1692       if (ix1) *ix1 = 0;
   1693       if (iy1) *iy1 = 0;
   1694    } else {
   1695       // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
   1696       if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
   1697       if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
   1698       if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
   1699       if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
   1700    }
   1701 }
   1702 
   1703 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)
   1704 {
   1705    stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
   1706 }
   1707 
   1708 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)
   1709 {
   1710    stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
   1711 }
   1712 
   1713 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)
   1714 {
   1715    stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
   1716 }
   1717 
   1718 //////////////////////////////////////////////////////////////////////////////
   1719 //
   1720 //  Rasterizer
   1721 
   1722 typedef struct stbtt__hheap_chunk
   1723 {
   1724    struct stbtt__hheap_chunk *next;
   1725 } stbtt__hheap_chunk;
   1726 
   1727 typedef struct stbtt__hheap
   1728 {
   1729    struct stbtt__hheap_chunk *head;
   1730    void   *first_free;
   1731    int    num_remaining_in_head_chunk;
   1732 } stbtt__hheap;
   1733 
   1734 static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
   1735 {
   1736    if (hh->first_free) {
   1737       void *p = hh->first_free;
   1738       hh->first_free = * (void **) p;
   1739       return p;
   1740    } else {
   1741       if (hh->num_remaining_in_head_chunk == 0) {
   1742          int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
   1743          stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
   1744          if (c == NULL)
   1745             return NULL;
   1746          c->next = hh->head;
   1747          hh->head = c;
   1748          hh->num_remaining_in_head_chunk = count;
   1749       }
   1750       --hh->num_remaining_in_head_chunk;
   1751       return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
   1752    }
   1753 }
   1754 
   1755 static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
   1756 {
   1757    *(void **) p = hh->first_free;
   1758    hh->first_free = p;
   1759 }
   1760 
   1761 static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
   1762 {
   1763    stbtt__hheap_chunk *c = hh->head;
   1764    while (c) {
   1765       stbtt__hheap_chunk *n = c->next;
   1766       STBTT_free(c, userdata);
   1767       c = n;
   1768    }
   1769 }
   1770 
   1771 typedef struct stbtt__edge {
   1772    float x0,y0, x1,y1;
   1773    int invert;
   1774 } stbtt__edge;
   1775 
   1776 
   1777 typedef struct stbtt__active_edge
   1778 {
   1779    struct stbtt__active_edge *next;
   1780    #if STBTT_RASTERIZER_VERSION==1
   1781    int x,dx;
   1782    float ey;
   1783    int direction;
   1784    #elif STBTT_RASTERIZER_VERSION==2
   1785    float fx,fdx,fdy;
   1786    float direction;
   1787    float sy;
   1788    float ey;
   1789    #else
   1790    #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
   1791    #endif
   1792 } stbtt__active_edge;
   1793 
   1794 #if STBTT_RASTERIZER_VERSION == 1
   1795 #define STBTT_FIXSHIFT   10
   1796 #define STBTT_FIX        (1 << STBTT_FIXSHIFT)
   1797 #define STBTT_FIXMASK    (STBTT_FIX-1)
   1798 
   1799 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
   1800 {
   1801    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
   1802    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
   1803    STBTT_assert(z != NULL);
   1804    if (!z) return z;
   1805 
   1806    // round dx down to avoid overshooting
   1807    if (dxdy < 0)
   1808       z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
   1809    else
   1810       z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
   1811 
   1812    z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
   1813    z->x -= off_x * STBTT_FIX;
   1814 
   1815    z->ey = e->y1;
   1816    z->next = 0;
   1817    z->direction = e->invert ? 1 : -1;
   1818    return z;
   1819 }
   1820 #elif STBTT_RASTERIZER_VERSION == 2
   1821 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
   1822 {
   1823    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
   1824    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
   1825    STBTT_assert(z != NULL);
   1826    //STBTT_assert(e->y0 <= start_point);
   1827    if (!z) return z;
   1828    z->fdx = dxdy;
   1829    z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
   1830    z->fx = e->x0 + dxdy * (start_point - e->y0);
   1831    z->fx -= off_x;
   1832    z->direction = e->invert ? 1.0f : -1.0f;
   1833    z->sy = e->y0;
   1834    z->ey = e->y1;
   1835    z->next = 0;
   1836    return z;
   1837 }
   1838 #else
   1839 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
   1840 #endif
   1841 
   1842 #if STBTT_RASTERIZER_VERSION == 1
   1843 // note: this routine clips fills that extend off the edges... ideally this
   1844 // wouldn't happen, but it could happen if the truetype glyph bounding boxes
   1845 // are wrong, or if the user supplies a too-small bitmap
   1846 static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
   1847 {
   1848    // non-zero winding fill
   1849    int x0=0, w=0;
   1850 
   1851    while (e) {
   1852       if (w == 0) {
   1853          // if we're currently at zero, we need to record the edge start point
   1854          x0 = e->x; w += e->direction;
   1855       } else {
   1856          int x1 = e->x; w += e->direction;
   1857          // if we went to zero, we need to draw
   1858          if (w == 0) {
   1859             int i = x0 >> STBTT_FIXSHIFT;
   1860             int j = x1 >> STBTT_FIXSHIFT;
   1861 
   1862             if (i < len && j >= 0) {
   1863                if (i == j) {
   1864                   // x0,x1 are the same pixel, so compute combined coverage
   1865                   scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
   1866                } else {
   1867                   if (i >= 0) // add antialiasing for x0
   1868                      scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
   1869                   else
   1870                      i = -1; // clip
   1871 
   1872                   if (j < len) // add antialiasing for x1
   1873                      scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
   1874                   else
   1875                      j = len; // clip
   1876 
   1877                   for (++i; i < j; ++i) // fill pixels between x0 and x1
   1878                      scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
   1879                }
   1880             }
   1881          }
   1882       }
   1883 
   1884       e = e->next;
   1885    }
   1886 }
   1887 
   1888 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
   1889 {
   1890    stbtt__hheap hh = { 0, 0, 0 };
   1891    stbtt__active_edge *active = NULL;
   1892    int y,j=0;
   1893    int max_weight = (255 / vsubsample);  // weight per vertical scanline
   1894    int s; // vertical subsample index
   1895    unsigned char scanline_data[512], *scanline;
   1896 
   1897    if (result->w > 512)
   1898       scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
   1899    else
   1900       scanline = scanline_data;
   1901 
   1902    y = off_y * vsubsample;
   1903    e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
   1904 
   1905    while (j < result->h) {
   1906       STBTT_memset(scanline, 0, result->w);
   1907       for (s=0; s < vsubsample; ++s) {
   1908          // find center of pixel for this scanline
   1909          float scan_y = y + 0.5f;
   1910          stbtt__active_edge **step = &active;
   1911 
   1912          // update all active edges;
   1913          // remove all active edges that terminate before the center of this scanline
   1914          while (*step) {
   1915             stbtt__active_edge * z = *step;
   1916             if (z->ey <= scan_y) {
   1917                *step = z->next; // delete from list
   1918                STBTT_assert(z->direction);
   1919                z->direction = 0;
   1920                stbtt__hheap_free(&hh, z);
   1921             } else {
   1922                z->x += z->dx; // advance to position for current scanline
   1923                step = &((*step)->next); // advance through list
   1924             }
   1925          }
   1926 
   1927          // resort the list if needed
   1928          for(;;) {
   1929             int changed=0;
   1930             step = &active;
   1931             while (*step && (*step)->next) {
   1932                if ((*step)->x > (*step)->next->x) {
   1933                   stbtt__active_edge *t = *step;
   1934                   stbtt__active_edge *q = t->next;
   1935 
   1936                   t->next = q->next;
   1937                   q->next = t;
   1938                   *step = q;
   1939                   changed = 1;
   1940                }
   1941                step = &(*step)->next;
   1942             }
   1943             if (!changed) break;
   1944          }
   1945 
   1946          // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
   1947          while (e->y0 <= scan_y) {
   1948             if (e->y1 > scan_y) {
   1949                stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
   1950                if (z != NULL) {
   1951                   // find insertion point
   1952                   if (active == NULL)
   1953                      active = z;
   1954                   else if (z->x < active->x) {
   1955                      // insert at front
   1956                      z->next = active;
   1957                      active = z;
   1958                   } else {
   1959                      // find thing to insert AFTER
   1960                      stbtt__active_edge *p = active;
   1961                      while (p->next && p->next->x < z->x)
   1962                         p = p->next;
   1963                      // at this point, p->next->x is NOT < z->x
   1964                      z->next = p->next;
   1965                      p->next = z;
   1966                   }
   1967                }
   1968             }
   1969             ++e;
   1970          }
   1971 
   1972          // now process all active edges in XOR fashion
   1973          if (active)
   1974             stbtt__fill_active_edges(scanline, result->w, active, max_weight);
   1975 
   1976          ++y;
   1977       }
   1978       STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
   1979       ++j;
   1980    }
   1981 
   1982    stbtt__hheap_cleanup(&hh, userdata);
   1983 
   1984    if (scanline != scanline_data)
   1985       STBTT_free(scanline, userdata);
   1986 }
   1987 
   1988 #elif STBTT_RASTERIZER_VERSION == 2
   1989 
   1990 // the edge passed in here does not cross the vertical line at x or the vertical line at x+1
   1991 // (i.e. it has already been clipped to those)
   1992 static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
   1993 {
   1994    if (y0 == y1) return;
   1995    STBTT_assert(y0 < y1);
   1996    STBTT_assert(e->sy <= e->ey);
   1997    if (y0 > e->ey) return;
   1998    if (y1 < e->sy) return;
   1999    if (y0 < e->sy) {
   2000       x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
   2001       y0 = e->sy;
   2002    }
   2003    if (y1 > e->ey) {
   2004       x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
   2005       y1 = e->ey;
   2006    }
   2007 
   2008    if (x0 == x)
   2009       STBTT_assert(x1 <= x+1);
   2010    else if (x0 == x+1)
   2011       STBTT_assert(x1 >= x);
   2012    else if (x0 <= x)
   2013       STBTT_assert(x1 <= x);
   2014    else if (x0 >= x+1)
   2015       STBTT_assert(x1 >= x+1);
   2016    else
   2017       STBTT_assert(x1 >= x && x1 <= x+1);
   2018 
   2019    if (x0 <= x && x1 <= x)
   2020       scanline[x] += e->direction * (y1-y0);
   2021    else if (x0 >= x+1 && x1 >= x+1)
   2022       ;
   2023    else {
   2024       STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
   2025       scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
   2026    }
   2027 }
   2028 
   2029 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
   2030 {
   2031    float y_bottom = y_top+1;
   2032 
   2033    while (e) {
   2034       // brute force every pixel
   2035 
   2036       // compute intersection points with top & bottom
   2037       STBTT_assert(e->ey >= y_top);
   2038 
   2039       if (e->fdx == 0) {
   2040          float x0 = e->fx;
   2041          if (x0 < len) {
   2042             if (x0 >= 0) {
   2043                stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
   2044                stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
   2045             } else {
   2046                stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
   2047             }
   2048          }
   2049       } else {
   2050          float x0 = e->fx;
   2051          float dx = e->fdx;
   2052          float xb = x0 + dx;
   2053          float x_top, x_bottom;
   2054          float sy0,sy1;
   2055          float dy = e->fdy;
   2056          STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
   2057 
   2058          // compute endpoints of line segment clipped to this scanline (if the
   2059          // line segment starts on this scanline. x0 is the intersection of the
   2060          // line with y_top, but that may be off the line segment.
   2061          if (e->sy > y_top) {
   2062             x_top = x0 + dx * (e->sy - y_top);
   2063             sy0 = e->sy;
   2064          } else {
   2065             x_top = x0;
   2066             sy0 = y_top;
   2067          }
   2068          if (e->ey < y_bottom) {
   2069             x_bottom = x0 + dx * (e->ey - y_top);
   2070             sy1 = e->ey;
   2071          } else {
   2072             x_bottom = xb;
   2073             sy1 = y_bottom;
   2074          }
   2075 
   2076          if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
   2077             // from here on, we don't have to range check x values
   2078 
   2079             if ((int) x_top == (int) x_bottom) {
   2080                float height;
   2081                // simple case, only spans one pixel
   2082                int x = (int) x_top;
   2083                height = sy1 - sy0;
   2084                STBTT_assert(x >= 0 && x < len);
   2085                scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2)  * height;
   2086                scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
   2087             } else {
   2088                int x,x1,x2;
   2089                float y_crossing, step, sign, area;
   2090                // covers 2+ pixels
   2091                if (x_top > x_bottom) {
   2092                   // flip scanline vertically; signed area is the same
   2093                   float t;
   2094                   sy0 = y_bottom - (sy0 - y_top);
   2095                   sy1 = y_bottom - (sy1 - y_top);
   2096                   t = sy0, sy0 = sy1, sy1 = t;
   2097                   t = x_bottom, x_bottom = x_top, x_top = t;
   2098                   dx = -dx;
   2099                   dy = -dy;
   2100                   t = x0, x0 = xb, xb = t;
   2101                }
   2102 
   2103                x1 = (int) x_top;
   2104                x2 = (int) x_bottom;
   2105                // compute intersection with y axis at x1+1
   2106                y_crossing = (x1+1 - x0) * dy + y_top;
   2107 
   2108                sign = e->direction;
   2109                // area of the rectangle covered from y0..y_crossing
   2110                area = sign * (y_crossing-sy0);
   2111                // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
   2112                scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
   2113 
   2114                step = sign * dy;
   2115                for (x = x1+1; x < x2; ++x) {
   2116                   scanline[x] += area + step/2;
   2117                   area += step;
   2118                }
   2119                y_crossing += dy * (x2 - (x1+1));
   2120 
   2121                STBTT_assert(STBTT_fabs(area) <= 1.01f);
   2122 
   2123                scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
   2124 
   2125                scanline_fill[x2] += sign * (sy1-sy0);
   2126             }
   2127          } else {
   2128             // if edge goes outside of box we're drawing, we require
   2129             // clipping logic. since this does not match the intended use
   2130             // of this library, we use a different, very slow brute
   2131             // force implementation
   2132             int x;
   2133             for (x=0; x < len; ++x) {
   2134                // cases:
   2135                //
   2136                // there can be up to two intersections with the pixel. any intersection
   2137                // with left or right edges can be handled by splitting into two (or three)
   2138                // regions. intersections with top & bottom do not necessitate case-wise logic.
   2139                //
   2140                // the old way of doing this found the intersections with the left & right edges,
   2141                // then used some simple logic to produce up to three segments in sorted order
   2142                // from top-to-bottom. however, this had a problem: if an x edge was epsilon
   2143                // across the x border, then the corresponding y position might not be distinct
   2144                // from the other y segment, and it might ignored as an empty segment. to avoid
   2145                // that, we need to explicitly produce segments based on x positions.
   2146 
   2147                // rename variables to clearly-defined pairs
   2148                float y0 = y_top;
   2149                float x1 = (float) (x);
   2150                float x2 = (float) (x+1);
   2151                float x3 = xb;
   2152                float y3 = y_bottom;
   2153 
   2154                // x = e->x + e->dx * (y-y_top)
   2155                // (y-y_top) = (x - e->x) / e->dx
   2156                // y = (x - e->x) / e->dx + y_top
   2157                float y1 = (x - x0) / dx + y_top;
   2158                float y2 = (x+1 - x0) / dx + y_top;
   2159 
   2160                if (x0 < x1 && x3 > x2) {         // three segments descending down-right
   2161                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
   2162                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
   2163                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
   2164                } else if (x3 < x1 && x0 > x2) {  // three segments descending down-left
   2165                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
   2166                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
   2167                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
   2168                } else if (x0 < x1 && x3 > x1) {  // two segments across x, down-right
   2169                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
   2170                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
   2171                } else if (x3 < x1 && x0 > x1) {  // two segments across x, down-left
   2172                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
   2173                   stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
   2174                } else if (x0 < x2 && x3 > x2) {  // two segments across x+1, down-right
   2175                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
   2176                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
   2177                } else if (x3 < x2 && x0 > x2) {  // two segments across x+1, down-left
   2178                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
   2179                   stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
   2180                } else {  // one segment
   2181                   stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
   2182                }
   2183             }
   2184          }
   2185       }
   2186       e = e->next;
   2187    }
   2188 }
   2189 
   2190 // directly AA rasterize edges w/o supersampling
   2191 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
   2192 {
   2193    stbtt__hheap hh = { 0, 0, 0 };
   2194    stbtt__active_edge *active = NULL;
   2195    int y,j=0, i;
   2196    float scanline_data[129], *scanline, *scanline2;
   2197 
   2198    STBTT__NOTUSED(vsubsample);
   2199 
   2200    if (result->w > 64)
   2201       scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
   2202    else
   2203       scanline = scanline_data;
   2204 
   2205    scanline2 = scanline + result->w;
   2206 
   2207    y = off_y;
   2208    e[n].y0 = (float) (off_y + result->h) + 1;
   2209 
   2210    while (j < result->h) {
   2211       // find center of pixel for this scanline
   2212       float scan_y_top    = y + 0.0f;
   2213       float scan_y_bottom = y + 1.0f;
   2214       stbtt__active_edge **step = &active;
   2215 
   2216       STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
   2217       STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
   2218 
   2219       // update all active edges;
   2220       // remove all active edges that terminate before the top of this scanline
   2221       while (*step) {
   2222          stbtt__active_edge * z = *step;
   2223          if (z->ey <= scan_y_top) {
   2224             *step = z->next; // delete from list
   2225             STBTT_assert(z->direction);
   2226             z->direction = 0;
   2227             stbtt__hheap_free(&hh, z);
   2228          } else {
   2229             step = &((*step)->next); // advance through list
   2230          }
   2231       }
   2232 
   2233       // insert all edges that start before the bottom of this scanline
   2234       while (e->y0 <= scan_y_bottom) {
   2235          if (e->y0 != e->y1) {
   2236             stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
   2237             if (z != NULL) {
   2238                if (j == 0 && off_y != 0) {
   2239                   if (z->ey < scan_y_top) {
   2240                      // this can happen due to subpixel positioning and some kind of fp rounding error i think
   2241                      z->ey = scan_y_top;
   2242                   }
   2243                }
   2244                STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
   2245                // insert at front
   2246                z->next = active;
   2247                active = z;
   2248             }
   2249          }
   2250          ++e;
   2251       }
   2252 
   2253       // now process all active edges
   2254       if (active)
   2255          stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
   2256 
   2257       {
   2258          float sum = 0;
   2259          for (i=0; i < result->w; ++i) {
   2260             float k;
   2261             int m;
   2262             sum += scanline2[i];
   2263             k = scanline[i] + sum;
   2264             k = (float) STBTT_fabs(k)*255 + 0.5f;
   2265             m = (int) k;
   2266             if (m > 255) m = 255;
   2267             result->pixels[j*result->stride + i] = (unsigned char) m;
   2268          }
   2269       }
   2270       // advance all the edges
   2271       step = &active;
   2272       while (*step) {
   2273          stbtt__active_edge *z = *step;
   2274          z->fx += z->fdx; // advance to position for current scanline
   2275          step = &((*step)->next); // advance through list
   2276       }
   2277 
   2278       ++y;
   2279       ++j;
   2280    }
   2281 
   2282    stbtt__hheap_cleanup(&hh, userdata);
   2283 
   2284    if (scanline != scanline_data)
   2285       STBTT_free(scanline, userdata);
   2286 }
   2287 #else
   2288 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
   2289 #endif
   2290 
   2291 #define STBTT__COMPARE(a,b)  ((a)->y0 < (b)->y0)
   2292 
   2293 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
   2294 {
   2295    int i,j;
   2296    for (i=1; i < n; ++i) {
   2297       stbtt__edge t = p[i], *a = &t;
   2298       j = i;
   2299       while (j > 0) {
   2300          stbtt__edge *b = &p[j-1];
   2301          int c = STBTT__COMPARE(a,b);
   2302          if (!c) break;
   2303          p[j] = p[j-1];
   2304          --j;
   2305       }
   2306       if (i != j)
   2307          p[j] = t;
   2308    }
   2309 }
   2310 
   2311 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
   2312 {
   2313    /* threshold for transitioning to insertion sort */
   2314    while (n > 12) {
   2315       stbtt__edge t;
   2316       int c01,c12,c,m,i,j;
   2317 
   2318       /* compute median of three */
   2319       m = n >> 1;
   2320       c01 = STBTT__COMPARE(&p[0],&p[m]);
   2321       c12 = STBTT__COMPARE(&p[m],&p[n-1]);
   2322       /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
   2323       if (c01 != c12) {
   2324          /* otherwise, we'll need to swap something else to middle */
   2325          int z;
   2326          c = STBTT__COMPARE(&p[0],&p[n-1]);
   2327          /* 0>mid && mid<n:  0>n => n; 0<n => 0 */
   2328          /* 0<mid && mid>n:  0>n => 0; 0<n => n */
   2329          z = (c == c12) ? 0 : n-1;
   2330          t = p[z];
   2331          p[z] = p[m];
   2332          p[m] = t;
   2333       }
   2334       /* now p[m] is the median-of-three */
   2335       /* swap it to the beginning so it won't move around */
   2336       t = p[0];
   2337       p[0] = p[m];
   2338       p[m] = t;
   2339 
   2340       /* partition loop */
   2341       i=1;
   2342       j=n-1;
   2343       for(;;) {
   2344          /* handling of equality is crucial here */
   2345          /* for sentinels & efficiency with duplicates */
   2346          for (;;++i) {
   2347             if (!STBTT__COMPARE(&p[i], &p[0])) break;
   2348          }
   2349          for (;;--j) {
   2350             if (!STBTT__COMPARE(&p[0], &p[j])) break;
   2351          }
   2352          /* make sure we haven't crossed */
   2353          if (i >= j) break;
   2354          t = p[i];
   2355          p[i] = p[j];
   2356          p[j] = t;
   2357 
   2358          ++i;
   2359          --j;
   2360       }
   2361       /* recurse on smaller side, iterate on larger */
   2362       if (j < (n-i)) {
   2363          stbtt__sort_edges_quicksort(p,j);
   2364          p = p+i;
   2365          n = n-i;
   2366       } else {
   2367          stbtt__sort_edges_quicksort(p+i, n-i);
   2368          n = j;
   2369       }
   2370    }
   2371 }
   2372 
   2373 static void stbtt__sort_edges(stbtt__edge *p, int n)
   2374 {
   2375    stbtt__sort_edges_quicksort(p, n);
   2376    stbtt__sort_edges_ins_sort(p, n);
   2377 }
   2378 
   2379 typedef struct
   2380 {
   2381    float x,y;
   2382 } stbtt__point;
   2383 
   2384 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)
   2385 {
   2386    float y_scale_inv = invert ? -scale_y : scale_y;
   2387    stbtt__edge *e;
   2388    int n,i,j,k,m;
   2389 #if STBTT_RASTERIZER_VERSION == 1
   2390    int vsubsample = result->h < 8 ? 15 : 5;
   2391 #elif STBTT_RASTERIZER_VERSION == 2
   2392    int vsubsample = 1;
   2393 #else
   2394    #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
   2395 #endif
   2396    // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
   2397 
   2398    // now we have to blow out the windings into explicit edge lists
   2399    n = 0;
   2400    for (i=0; i < windings; ++i)
   2401       n += wcount[i];
   2402 
   2403    e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
   2404    if (e == 0) return;
   2405    n = 0;
   2406 
   2407    m=0;
   2408    for (i=0; i < windings; ++i) {
   2409       stbtt__point *p = pts + m;
   2410       m += wcount[i];
   2411       j = wcount[i]-1;
   2412       for (k=0; k < wcount[i]; j=k++) {
   2413          int a=k,b=j;
   2414          // skip the edge if horizontal
   2415          if (p[j].y == p[k].y)
   2416             continue;
   2417          // add edge from j to k to the list
   2418          e[n].invert = 0;
   2419          if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
   2420             e[n].invert = 1;
   2421             a=j,b=k;
   2422          }
   2423          e[n].x0 = p[a].x * scale_x + shift_x;
   2424          e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
   2425          e[n].x1 = p[b].x * scale_x + shift_x;
   2426          e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
   2427          ++n;
   2428       }
   2429    }
   2430 
   2431    // now sort the edges by their highest point (should snap to integer, and then by x)
   2432    //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
   2433    stbtt__sort_edges(e, n);
   2434 
   2435    // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
   2436    stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
   2437 
   2438    STBTT_free(e, userdata);
   2439 }
   2440 
   2441 static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
   2442 {
   2443    if (!points) return; // during first pass, it's unallocated
   2444    points[n].x = x;
   2445    points[n].y = y;
   2446 }
   2447 
   2448 // tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
   2449 static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
   2450 {
   2451    // midpoint
   2452    float mx = (x0 + 2*x1 + x2)/4;
   2453    float my = (y0 + 2*y1 + y2)/4;
   2454    // versus directly drawn line
   2455    float dx = (x0+x2)/2 - mx;
   2456    float dy = (y0+y2)/2 - my;
   2457    if (n > 16) // 65536 segments on one curve better be enough!
   2458       return 1;
   2459    if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
   2460       stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
   2461       stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
   2462    } else {
   2463       stbtt__add_point(points, *num_points,x2,y2);
   2464       *num_points = *num_points+1;
   2465    }
   2466    return 1;
   2467 }
   2468 
   2469 static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
   2470 {
   2471    // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
   2472    float dx0 = x1-x0;
   2473    float dy0 = y1-y0;
   2474    float dx1 = x2-x1;
   2475    float dy1 = y2-y1;
   2476    float dx2 = x3-x2;
   2477    float dy2 = y3-y2;
   2478    float dx = x3-x0;
   2479    float dy = y3-y0;
   2480    float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
   2481    float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
   2482    float flatness_squared = longlen*longlen-shortlen*shortlen;
   2483 
   2484    if (n > 16) // 65536 segments on one curve better be enough!
   2485       return;
   2486 
   2487    if (flatness_squared > objspace_flatness_squared) {
   2488       float x01 = (x0+x1)/2;
   2489       float y01 = (y0+y1)/2;
   2490       float x12 = (x1+x2)/2;
   2491       float y12 = (y1+y2)/2;
   2492       float x23 = (x2+x3)/2;
   2493       float y23 = (y2+y3)/2;
   2494 
   2495       float xa = (x01+x12)/2;
   2496       float ya = (y01+y12)/2;
   2497       float xb = (x12+x23)/2;
   2498       float yb = (y12+y23)/2;
   2499 
   2500       float mx = (xa+xb)/2;
   2501       float my = (ya+yb)/2;
   2502 
   2503       stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
   2504       stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
   2505    } else {
   2506       stbtt__add_point(points, *num_points,x3,y3);
   2507       *num_points = *num_points+1;
   2508    }
   2509 }
   2510 
   2511 // returns number of contours
   2512 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
   2513 {
   2514    stbtt__point *points=0;
   2515    int num_points=0;
   2516 
   2517    float objspace_flatness_squared = objspace_flatness * objspace_flatness;
   2518    int i,n=0,start=0, pass;
   2519 
   2520    // count how many "moves" there are to get the contour count
   2521    for (i=0; i < num_verts; ++i)
   2522       if (vertices[i].type == STBTT_vmove)
   2523          ++n;
   2524 
   2525    *num_contours = n;
   2526    if (n == 0) return 0;
   2527 
   2528    *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
   2529 
   2530    if (*contour_lengths == 0) {
   2531       *num_contours = 0;
   2532       return 0;
   2533    }
   2534 
   2535    // make two passes through the points so we don't need to realloc
   2536    for (pass=0; pass < 2; ++pass) {
   2537       float x=0,y=0;
   2538       if (pass == 1) {
   2539          points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
   2540          if (points == NULL) goto error;
   2541       }
   2542       num_points = 0;
   2543       n= -1;
   2544       for (i=0; i < num_verts; ++i) {
   2545          switch (vertices[i].type) {
   2546             case STBTT_vmove:
   2547                // start the next contour
   2548                if (n >= 0)
   2549                   (*contour_lengths)[n] = num_points - start;
   2550                ++n;
   2551                start = num_points;
   2552 
   2553                x = vertices[i].x, y = vertices[i].y;
   2554                stbtt__add_point(points, num_points++, x,y);
   2555                break;
   2556             case STBTT_vline:
   2557                x = vertices[i].x, y = vertices[i].y;
   2558                stbtt__add_point(points, num_points++, x, y);
   2559                break;
   2560             case STBTT_vcurve:
   2561                stbtt__tesselate_curve(points, &num_points, x,y,
   2562                                         vertices[i].cx, vertices[i].cy,
   2563                                         vertices[i].x,  vertices[i].y,
   2564                                         objspace_flatness_squared, 0);
   2565                x = vertices[i].x, y = vertices[i].y;
   2566                break;
   2567             case STBTT_vcubic:
   2568                stbtt__tesselate_cubic(points, &num_points, x,y,
   2569                                         vertices[i].cx, vertices[i].cy,
   2570                                         vertices[i].cx1, vertices[i].cy1,
   2571                                         vertices[i].x,  vertices[i].y,
   2572                                         objspace_flatness_squared, 0);
   2573                x = vertices[i].x, y = vertices[i].y;
   2574                break;
   2575          }
   2576       }
   2577       (*contour_lengths)[n] = num_points - start;
   2578    }
   2579 
   2580    return points;
   2581 error:
   2582    STBTT_free(points, userdata);
   2583    STBTT_free(*contour_lengths, userdata);
   2584    *contour_lengths = 0;
   2585    *num_contours = 0;
   2586    return NULL;
   2587 }
   2588 
   2589 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)
   2590 {
   2591    float scale            = scale_x > scale_y ? scale_y : scale_x;
   2592    int winding_count      = 0;
   2593    int *winding_lengths   = NULL;
   2594    stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
   2595    if (windings) {
   2596       stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
   2597       STBTT_free(winding_lengths, userdata);
   2598       STBTT_free(windings, userdata);
   2599    }
   2600 }
   2601 
   2602 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
   2603 {
   2604    STBTT_free(bitmap, userdata);
   2605 }
   2606 
   2607 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)
   2608 {
   2609    int ix0,iy0,ix1,iy1;
   2610    stbtt__bitmap gbm;
   2611    stbtt_vertex *vertices;
   2612    int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
   2613 
   2614    if (scale_x == 0) scale_x = scale_y;
   2615    if (scale_y == 0) {
   2616       if (scale_x == 0) {
   2617          STBTT_free(vertices, info->userdata);
   2618          return NULL;
   2619       }
   2620       scale_y = scale_x;
   2621    }
   2622 
   2623    stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
   2624 
   2625    // now we get the size
   2626    gbm.w = (ix1 - ix0);
   2627    gbm.h = (iy1 - iy0);
   2628    gbm.pixels = NULL; // in case we error
   2629 
   2630    if (width ) *width  = gbm.w;
   2631    if (height) *height = gbm.h;
   2632    if (xoff  ) *xoff   = ix0;
   2633    if (yoff  ) *yoff   = iy0;
   2634 
   2635    if (gbm.w && gbm.h) {
   2636       gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
   2637       if (gbm.pixels) {
   2638          gbm.stride = gbm.w;
   2639 
   2640          stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
   2641       }
   2642    }
   2643    STBTT_free(vertices, info->userdata);
   2644    return gbm.pixels;
   2645 }
   2646 
   2647 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)
   2648 {
   2649    return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
   2650 }
   2651 
   2652 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)
   2653 {
   2654    int ix0,iy0;
   2655    stbtt_vertex *vertices;
   2656    int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
   2657    stbtt__bitmap gbm;
   2658 
   2659    stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
   2660    gbm.pixels = output;
   2661    gbm.w = out_w;
   2662    gbm.h = out_h;
   2663    gbm.stride = out_stride;
   2664 
   2665    if (gbm.w && gbm.h)
   2666       stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
   2667 
   2668    STBTT_free(vertices, info->userdata);
   2669 }
   2670 
   2671 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)
   2672 {
   2673    stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
   2674 }
   2675 
   2676 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)
   2677 {
   2678    return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
   2679 }
   2680 
   2681 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(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 oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
   2682 {
   2683    stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
   2684 }
   2685 
   2686 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)
   2687 {
   2688    stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
   2689 }
   2690 
   2691 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)
   2692 {
   2693    return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
   2694 }
   2695 
   2696 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)
   2697 {
   2698    stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
   2699 }
   2700 
   2701 //////////////////////////////////////////////////////////////////////////////
   2702 //
   2703 // bitmap baking
   2704 //
   2705 // This is SUPER-CRAPPY packing to keep source code small
   2706 
   2707 static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)
   2708                                 float pixel_height,                     // height of font in pixels
   2709                                 unsigned char *pixels, int pw, int ph,  // bitmap to be filled in
   2710                                 int first_char, int num_chars,          // characters to bake
   2711                                 stbtt_bakedchar *chardata)
   2712 {
   2713    float scale;
   2714    int x,y,bottom_y, i;
   2715    stbtt_fontinfo f;
   2716    f.userdata = NULL;
   2717    if (!stbtt_InitFont(&f, data, offset))
   2718       return -1;
   2719    STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
   2720    x=y=1;
   2721    bottom_y = 1;
   2722 
   2723    scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
   2724 
   2725    for (i=0; i < num_chars; ++i) {
   2726       int advance, lsb, x0,y0,x1,y1,gw,gh;
   2727       int g = stbtt_FindGlyphIndex(&f, first_char + i);
   2728       stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
   2729       stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
   2730       gw = x1-x0;
   2731       gh = y1-y0;
   2732       if (x + gw + 1 >= pw)
   2733          y = bottom_y, x = 1; // advance to next row
   2734       if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
   2735          return -i;
   2736       STBTT_assert(x+gw < pw);
   2737       STBTT_assert(y+gh < ph);
   2738       stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
   2739       chardata[i].x0 = (stbtt_int16) x;
   2740       chardata[i].y0 = (stbtt_int16) y;
   2741       chardata[i].x1 = (stbtt_int16) (x + gw);
   2742       chardata[i].y1 = (stbtt_int16) (y + gh);
   2743       chardata[i].xadvance = scale * advance;
   2744       chardata[i].xoff     = (float) x0;
   2745       chardata[i].yoff     = (float) y0;
   2746       x = x + gw + 1;
   2747       if (y+gh+1 > bottom_y)
   2748          bottom_y = y+gh+1;
   2749    }
   2750    return bottom_y;
   2751 }
   2752 
   2753 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
   2754 {
   2755    float d3d_bias = opengl_fillrule ? 0 : -0.5f;
   2756    float ipw = 1.0f / pw, iph = 1.0f / ph;
   2757    const stbtt_bakedchar *b = chardata + char_index;
   2758    int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
   2759    int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
   2760 
   2761    q->x0 = round_x + d3d_bias;
   2762    q->y0 = round_y + d3d_bias;
   2763    q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
   2764    q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
   2765 
   2766    q->s0 = b->x0 * ipw;
   2767    q->t0 = b->y0 * iph;
   2768    q->s1 = b->x1 * ipw;
   2769    q->t1 = b->y1 * iph;
   2770 
   2771    *xpos += b->xadvance;
   2772 }
   2773 
   2774 //////////////////////////////////////////////////////////////////////////////
   2775 //
   2776 // rectangle packing replacement routines if you don't have stb_rect_pack.h
   2777 //
   2778 
   2779 #ifndef STB_RECT_PACK_VERSION
   2780 
   2781 typedef int stbrp_coord;
   2782 
   2783 ////////////////////////////////////////////////////////////////////////////////////
   2784 //                                                                                //
   2785 //                                                                                //
   2786 // COMPILER WARNING ?!?!?                                                         //
   2787 //                                                                                //
   2788 //                                                                                //
   2789 // if you get a compile warning due to these symbols being defined more than      //
   2790 // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h"         //
   2791 //                                                                                //
   2792 ////////////////////////////////////////////////////////////////////////////////////
   2793 
   2794 typedef struct
   2795 {
   2796    int width,height;
   2797    int x,y,bottom_y;
   2798 } stbrp_context;
   2799 
   2800 typedef struct
   2801 {
   2802    unsigned char x;
   2803 } stbrp_node;
   2804 
   2805 struct stbrp_rect
   2806 {
   2807    stbrp_coord x,y;
   2808    int id,w,h,was_packed;
   2809 };
   2810 
   2811 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
   2812 {
   2813    con->width  = pw;
   2814    con->height = ph;
   2815    con->x = 0;
   2816    con->y = 0;
   2817    con->bottom_y = 0;
   2818    STBTT__NOTUSED(nodes);
   2819    STBTT__NOTUSED(num_nodes);
   2820 }
   2821 
   2822 static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
   2823 {
   2824    int i;
   2825    for (i=0; i < num_rects; ++i) {
   2826       if (con->x + rects[i].w > con->width) {
   2827          con->x = 0;
   2828          con->y = con->bottom_y;
   2829       }
   2830       if (con->y + rects[i].h > con->height)
   2831          break;
   2832       rects[i].x = con->x;
   2833       rects[i].y = con->y;
   2834       rects[i].was_packed = 1;
   2835       con->x += rects[i].w;
   2836       if (con->y + rects[i].h > con->bottom_y)
   2837          con->bottom_y = con->y + rects[i].h;
   2838    }
   2839    for (   ; i < num_rects; ++i)
   2840       rects[i].was_packed = 0;
   2841 }
   2842 #endif
   2843 
   2844 //////////////////////////////////////////////////////////////////////////////
   2845 //
   2846 // bitmap baking
   2847 //
   2848 // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
   2849 // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
   2850 
   2851 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)
   2852 {
   2853    stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context)            ,alloc_context);
   2854    int            num_nodes = pw - padding;
   2855    stbrp_node    *nodes   = (stbrp_node    *) STBTT_malloc(sizeof(*nodes  ) * num_nodes,alloc_context);
   2856 
   2857    if (context == NULL || nodes == NULL) {
   2858       if (context != NULL) STBTT_free(context, alloc_context);
   2859       if (nodes   != NULL) STBTT_free(nodes  , alloc_context);
   2860       return 0;
   2861    }
   2862 
   2863    spc->user_allocator_context = alloc_context;
   2864    spc->width = pw;
   2865    spc->height = ph;
   2866    spc->pixels = pixels;
   2867    spc->pack_info = context;
   2868    spc->nodes = nodes;
   2869    spc->padding = padding;
   2870    spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
   2871    spc->h_oversample = 1;
   2872    spc->v_oversample = 1;
   2873    spc->skip_missing = 0;
   2874 
   2875    stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
   2876 
   2877    if (pixels)
   2878       STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
   2879 
   2880    return 1;
   2881 }
   2882 
   2883 STBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc)
   2884 {
   2885    STBTT_free(spc->nodes    , spc->user_allocator_context);
   2886    STBTT_free(spc->pack_info, spc->user_allocator_context);
   2887 }
   2888 
   2889 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
   2890 {
   2891    STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
   2892    STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
   2893    if (h_oversample <= STBTT_MAX_OVERSAMPLE)
   2894       spc->h_oversample = h_oversample;
   2895    if (v_oversample <= STBTT_MAX_OVERSAMPLE)
   2896       spc->v_oversample = v_oversample;
   2897 }
   2898 
   2899 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
   2900 {
   2901    spc->skip_missing = skip;
   2902 }
   2903 
   2904 #define STBTT__OVER_MASK  (STBTT_MAX_OVERSAMPLE-1)
   2905 
   2906 static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
   2907 {
   2908    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
   2909    int safe_w = w - kernel_width;
   2910    int j;
   2911    STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
   2912    for (j=0; j < h; ++j) {
   2913       int i;
   2914       unsigned int total;
   2915       STBTT_memset(buffer, 0, kernel_width);
   2916 
   2917       total = 0;
   2918 
   2919       // make kernel_width a constant in common cases so compiler can optimize out the divide
   2920       switch (kernel_width) {
   2921          case 2:
   2922             for (i=0; i <= safe_w; ++i) {
   2923                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
   2924                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
   2925                pixels[i] = (unsigned char) (total / 2);
   2926             }
   2927             break;
   2928          case 3:
   2929             for (i=0; i <= safe_w; ++i) {
   2930                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
   2931                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
   2932                pixels[i] = (unsigned char) (total / 3);
   2933             }
   2934             break;
   2935          case 4:
   2936             for (i=0; i <= safe_w; ++i) {
   2937                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
   2938                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
   2939                pixels[i] = (unsigned char) (total / 4);
   2940             }
   2941             break;
   2942          case 5:
   2943             for (i=0; i <= safe_w; ++i) {
   2944                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
   2945                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
   2946                pixels[i] = (unsigned char) (total / 5);
   2947             }
   2948             break;
   2949          default:
   2950             for (i=0; i <= safe_w; ++i) {
   2951                total += pixels[i] - buffer[i & STBTT__OVER_MASK];
   2952                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
   2953                pixels[i] = (unsigned char) (total / kernel_width);
   2954             }
   2955             break;
   2956       }
   2957 
   2958       for (; i < w; ++i) {
   2959          STBTT_assert(pixels[i] == 0);
   2960          total -= buffer[i & STBTT__OVER_MASK];
   2961          pixels[i] = (unsigned char) (total / kernel_width);
   2962       }
   2963 
   2964       pixels += stride_in_bytes;
   2965    }
   2966 }
   2967 
   2968 static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
   2969 {
   2970    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
   2971    int safe_h = h - kernel_width;
   2972    int j;
   2973    STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
   2974    for (j=0; j < w; ++j) {
   2975       int i;
   2976       unsigned int total;
   2977       STBTT_memset(buffer, 0, kernel_width);
   2978 
   2979       total = 0;
   2980 
   2981       // make kernel_width a constant in common cases so compiler can optimize out the divide
   2982       switch (kernel_width) {
   2983          case 2:
   2984             for (i=0; i <= safe_h; ++i) {
   2985                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
   2986                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
   2987                pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
   2988             }
   2989             break;
   2990          case 3:
   2991             for (i=0; i <= safe_h; ++i) {
   2992                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
   2993                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
   2994                pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
   2995             }
   2996             break;
   2997          case 4:
   2998             for (i=0; i <= safe_h; ++i) {
   2999                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
   3000                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
   3001                pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
   3002             }
   3003             break;
   3004          case 5:
   3005             for (i=0; i <= safe_h; ++i) {
   3006                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
   3007                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
   3008                pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
   3009             }
   3010             break;
   3011          default:
   3012             for (i=0; i <= safe_h; ++i) {
   3013                total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
   3014                buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
   3015                pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
   3016             }
   3017             break;
   3018       }
   3019 
   3020       for (; i < h; ++i) {
   3021          STBTT_assert(pixels[i*stride_in_bytes] == 0);
   3022          total -= buffer[i & STBTT__OVER_MASK];
   3023          pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
   3024       }
   3025 
   3026       pixels += 1;
   3027    }
   3028 }
   3029 
   3030 static float stbtt__oversample_shift(int oversample)
   3031 {
   3032    if (!oversample)
   3033       return 0.0f;
   3034 
   3035    // The prefilter is a box filter of width "oversample",
   3036    // which shifts phase by (oversample - 1)/2 pixels in
   3037    // oversampled space. We want to shift in the opposite
   3038    // direction to counter this.
   3039    return (float)-(oversample - 1) / (2.0f * (float)oversample);
   3040 }
   3041 
   3042 // rects array must be big enough to accommodate all characters in the given ranges
   3043 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
   3044 {
   3045    int i,j,k;
   3046    int missing_glyph_added = 0;
   3047 
   3048    k=0;
   3049    for (i=0; i < num_ranges; ++i) {
   3050       float fh = ranges[i].font_size;
   3051       float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
   3052       ranges[i].h_oversample = (unsigned char) spc->h_oversample;
   3053       ranges[i].v_oversample = (unsigned char) spc->v_oversample;
   3054       for (j=0; j < ranges[i].num_chars; ++j) {
   3055          int x0,y0,x1,y1;
   3056          int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
   3057          int glyph = stbtt_FindGlyphIndex(info, codepoint);
   3058          if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
   3059             rects[k].w = rects[k].h = 0;
   3060          } else {
   3061             stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
   3062                                             scale * spc->h_oversample,
   3063                                             scale * spc->v_oversample,
   3064                                             0,0,
   3065                                             &x0,&y0,&x1,&y1);
   3066             rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
   3067             rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
   3068             if (glyph == 0)
   3069                missing_glyph_added = 1;
   3070          }
   3071          ++k;
   3072       }
   3073    }
   3074 
   3075    return k;
   3076 }
   3077 
   3078 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(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 prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
   3079 {
   3080    stbtt_MakeGlyphBitmapSubpixel(info,
   3081                                  output,
   3082                                  out_w - (prefilter_x - 1),
   3083                                  out_h - (prefilter_y - 1),
   3084                                  out_stride,
   3085                                  scale_x,
   3086                                  scale_y,
   3087                                  shift_x,
   3088                                  shift_y,
   3089                                  glyph);
   3090 
   3091    if (prefilter_x > 1)
   3092       stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
   3093 
   3094    if (prefilter_y > 1)
   3095       stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
   3096 
   3097    *sub_x = stbtt__oversample_shift(prefilter_x);
   3098    *sub_y = stbtt__oversample_shift(prefilter_y);
   3099 }
   3100 
   3101 // rects array must be big enough to accommodate all characters in the given ranges
   3102 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
   3103 {
   3104    int i,j,k, missing_glyph = -1, return_value = 1;
   3105 
   3106    // save current values
   3107    int old_h_over = spc->h_oversample;
   3108    int old_v_over = spc->v_oversample;
   3109 
   3110    k = 0;
   3111    for (i=0; i < num_ranges; ++i) {
   3112       float fh = ranges[i].font_size;
   3113       float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
   3114       float recip_h,recip_v,sub_x,sub_y;
   3115       spc->h_oversample = ranges[i].h_oversample;
   3116       spc->v_oversample = ranges[i].v_oversample;
   3117       recip_h = 1.0f / spc->h_oversample;
   3118       recip_v = 1.0f / spc->v_oversample;
   3119       sub_x = stbtt__oversample_shift(spc->h_oversample);
   3120       sub_y = stbtt__oversample_shift(spc->v_oversample);
   3121       for (j=0; j < ranges[i].num_chars; ++j) {
   3122          stbrp_rect *r = &rects[k];
   3123          if (r->was_packed && r->w != 0 && r->h != 0) {
   3124             stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
   3125             int advance, lsb, x0,y0,x1,y1;
   3126             int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
   3127             int glyph = stbtt_FindGlyphIndex(info, codepoint);
   3128             stbrp_coord pad = (stbrp_coord) spc->padding;
   3129 
   3130             // pad on left and top
   3131             r->x += pad;
   3132             r->y += pad;
   3133             r->w -= pad;
   3134             r->h -= pad;
   3135             stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
   3136             stbtt_GetGlyphBitmapBox(info, glyph,
   3137                                     scale * spc->h_oversample,
   3138                                     scale * spc->v_oversample,
   3139                                     &x0,&y0,&x1,&y1);
   3140             stbtt_MakeGlyphBitmapSubpixel(info,
   3141                                           spc->pixels + r->x + r->y*spc->stride_in_bytes,
   3142                                           r->w - spc->h_oversample+1,
   3143                                           r->h - spc->v_oversample+1,
   3144                                           spc->stride_in_bytes,
   3145                                           scale * spc->h_oversample,
   3146                                           scale * spc->v_oversample,
   3147                                           0,0,
   3148                                           glyph);
   3149 
   3150             if (spc->h_oversample > 1)
   3151                stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
   3152                                   r->w, r->h, spc->stride_in_bytes,
   3153                                   spc->h_oversample);
   3154 
   3155             if (spc->v_oversample > 1)
   3156                stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
   3157                                   r->w, r->h, spc->stride_in_bytes,
   3158                                   spc->v_oversample);
   3159 
   3160             bc->x0       = (stbtt_int16)  r->x;
   3161             bc->y0       = (stbtt_int16)  r->y;
   3162             bc->x1       = (stbtt_int16) (r->x + r->w);
   3163             bc->y1       = (stbtt_int16) (r->y + r->h);
   3164             bc->xadvance =                scale * advance;
   3165             bc->xoff     =       (float)  x0 * recip_h + sub_x;
   3166             bc->yoff     =       (float)  y0 * recip_v + sub_y;
   3167             bc->xoff2    =                (x0 + r->w) * recip_h + sub_x;
   3168             bc->yoff2    =                (y0 + r->h) * recip_v + sub_y;
   3169 
   3170             if (glyph == 0)
   3171                missing_glyph = j;
   3172          } else if (spc->skip_missing) {
   3173             return_value = 0;
   3174          } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
   3175             ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
   3176          } else {
   3177             return_value = 0; // if any fail, report failure
   3178          }
   3179 
   3180          ++k;
   3181       }
   3182    }
   3183 
   3184    // restore original values
   3185    spc->h_oversample = old_h_over;
   3186    spc->v_oversample = old_v_over;
   3187 
   3188    return return_value;
   3189 }
   3190 
   3191 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
   3192 {
   3193    stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
   3194 }
   3195 
   3196 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
   3197 {
   3198    stbtt_fontinfo info;
   3199    int i,j,n, return_value = 1;
   3200    //stbrp_context *context = (stbrp_context *) spc->pack_info;
   3201    stbrp_rect    *rects;
   3202 
   3203    // flag all characters as NOT packed
   3204    for (i=0; i < num_ranges; ++i)
   3205       for (j=0; j < ranges[i].num_chars; ++j)
   3206          ranges[i].chardata_for_range[j].x0 =
   3207          ranges[i].chardata_for_range[j].y0 =
   3208          ranges[i].chardata_for_range[j].x1 =
   3209          ranges[i].chardata_for_range[j].y1 = 0;
   3210 
   3211    n = 0;
   3212    for (i=0; i < num_ranges; ++i)
   3213       n += ranges[i].num_chars;
   3214 
   3215    rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
   3216    if (rects == NULL)
   3217       return 0;
   3218 
   3219    info.userdata = spc->user_allocator_context;
   3220    stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
   3221 
   3222    n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
   3223 
   3224    stbtt_PackFontRangesPackRects(spc, rects, n);
   3225 
   3226    return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
   3227 
   3228    STBTT_free(rects, spc->user_allocator_context);
   3229    return return_value;
   3230 }
   3231 
   3232 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
   3233             int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
   3234 {
   3235    stbtt_pack_range range;
   3236    range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
   3237    range.array_of_unicode_codepoints = NULL;
   3238    range.num_chars                   = num_chars_in_range;
   3239    range.chardata_for_range          = chardata_for_range;
   3240    range.font_size                   = font_size;
   3241    return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
   3242 }
   3243 
   3244 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
   3245 {
   3246    int i_ascent, i_descent, i_lineGap;
   3247    float scale;
   3248    stbtt_fontinfo info;
   3249    stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
   3250    scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
   3251    stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
   3252    *ascent  = (float) i_ascent  * scale;
   3253    *descent = (float) i_descent * scale;
   3254    *lineGap = (float) i_lineGap * scale;
   3255 }
   3256 
   3257 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
   3258 {
   3259    float ipw = 1.0f / pw, iph = 1.0f / ph;
   3260    const stbtt_packedchar *b = chardata + char_index;
   3261 
   3262    if (align_to_integer) {
   3263       float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
   3264       float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
   3265       q->x0 = x;
   3266       q->y0 = y;
   3267       q->x1 = x + b->xoff2 - b->xoff;
   3268       q->y1 = y + b->yoff2 - b->yoff;
   3269    } else {
   3270       q->x0 = *xpos + b->xoff;
   3271       q->y0 = *ypos + b->yoff;
   3272       q->x1 = *xpos + b->xoff2;
   3273       q->y1 = *ypos + b->yoff2;
   3274    }
   3275 
   3276    q->s0 = b->x0 * ipw;
   3277    q->t0 = b->y0 * iph;
   3278    q->s1 = b->x1 * ipw;
   3279    q->t1 = b->y1 * iph;
   3280 
   3281    *xpos += b->xadvance;
   3282 }
   3283 
   3284 //////////////////////////////////////////////////////////////////////////////
   3285 //
   3286 // sdf computation
   3287 //
   3288 
   3289 #define STBTT_min(a,b)  ((a) < (b) ? (a) : (b))
   3290 #define STBTT_max(a,b)  ((a) < (b) ? (b) : (a))
   3291 
   3292 static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
   3293 {
   3294    float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
   3295    float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
   3296    float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
   3297    float roperp = orig[1]*ray[0] - orig[0]*ray[1];
   3298 
   3299    float a = q0perp - 2*q1perp + q2perp;
   3300    float b = q1perp - q0perp;
   3301    float c = q0perp - roperp;
   3302 
   3303    float s0 = 0., s1 = 0.;
   3304    int num_s = 0;
   3305 
   3306    if (a != 0.0) {
   3307       float discr = b*b - a*c;
   3308       if (discr > 0.0) {
   3309          float rcpna = -1 / a;
   3310          float d = (float) STBTT_sqrt(discr);
   3311          s0 = (b+d) * rcpna;
   3312          s1 = (b-d) * rcpna;
   3313          if (s0 >= 0.0 && s0 <= 1.0)
   3314             num_s = 1;
   3315          if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
   3316             if (num_s == 0) s0 = s1;
   3317             ++num_s;
   3318          }
   3319       }
   3320    } else {
   3321       // 2*b*s + c = 0
   3322       // s = -c / (2*b)
   3323       s0 = c / (-2 * b);
   3324       if (s0 >= 0.0 && s0 <= 1.0)
   3325          num_s = 1;
   3326    }
   3327 
   3328    if (num_s == 0)
   3329       return 0;
   3330    else {
   3331       float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
   3332       float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
   3333 
   3334       float q0d =   q0[0]*rayn_x +   q0[1]*rayn_y;
   3335       float q1d =   q1[0]*rayn_x +   q1[1]*rayn_y;
   3336       float q2d =   q2[0]*rayn_x +   q2[1]*rayn_y;
   3337       float rod = orig[0]*rayn_x + orig[1]*rayn_y;
   3338 
   3339       float q10d = q1d - q0d;
   3340       float q20d = q2d - q0d;
   3341       float q0rd = q0d - rod;
   3342 
   3343       hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
   3344       hits[0][1] = a*s0+b;
   3345 
   3346       if (num_s > 1) {
   3347          hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
   3348          hits[1][1] = a*s1+b;
   3349          return 2;
   3350       } else {
   3351          return 1;
   3352       }
   3353    }
   3354 }
   3355 
   3356 static int equal(float *a, float *b)
   3357 {
   3358    return (a[0] == b[0] && a[1] == b[1]);
   3359 }
   3360 
   3361 static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
   3362 {
   3363    int i;
   3364    float orig[2], ray[2] = { 1, 0 };
   3365    float y_frac;
   3366    int winding = 0;
   3367 
   3368    orig[0] = x;
   3369    orig[1] = y;
   3370 
   3371    // make sure y never passes through a vertex of the shape
   3372    y_frac = (float) STBTT_fmod(y, 1.0f);
   3373    if (y_frac < 0.01f)
   3374       y += 0.01f;
   3375    else if (y_frac > 0.99f)
   3376       y -= 0.01f;
   3377    orig[1] = y;
   3378 
   3379    // test a ray from (-infinity,y) to (x,y)
   3380    for (i=0; i < nverts; ++i) {
   3381       if (verts[i].type == STBTT_vline) {
   3382          int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
   3383          int x1 = (int) verts[i  ].x, y1 = (int) verts[i  ].y;
   3384          if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
   3385             float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
   3386             if (x_inter < x)
   3387                winding += (y0 < y1) ? 1 : -1;
   3388          }
   3389       }
   3390       if (verts[i].type == STBTT_vcurve) {
   3391          int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
   3392          int x1 = (int) verts[i  ].cx, y1 = (int) verts[i  ].cy;
   3393          int x2 = (int) verts[i  ].x , y2 = (int) verts[i  ].y ;
   3394          int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
   3395          int by = STBTT_max(y0,STBTT_max(y1,y2));
   3396          if (y > ay && y < by && x > ax) {
   3397             float q0[2],q1[2],q2[2];
   3398             float hits[2][2];
   3399             q0[0] = (float)x0;
   3400             q0[1] = (float)y0;
   3401             q1[0] = (float)x1;
   3402             q1[1] = (float)y1;
   3403             q2[0] = (float)x2;
   3404             q2[1] = (float)y2;
   3405             if (equal(q0,q1) || equal(q1,q2)) {
   3406                x0 = (int)verts[i-1].x;
   3407                y0 = (int)verts[i-1].y;
   3408                x1 = (int)verts[i  ].x;
   3409                y1 = (int)verts[i  ].y;
   3410                if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
   3411                   float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
   3412                   if (x_inter < x)
   3413                      winding += (y0 < y1) ? 1 : -1;
   3414                }
   3415             } else {
   3416                int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
   3417                if (num_hits >= 1)
   3418                   if (hits[0][0] < 0)
   3419                      winding += (hits[0][1] < 0 ? -1 : 1);
   3420                if (num_hits >= 2)
   3421                   if (hits[1][0] < 0)
   3422                      winding += (hits[1][1] < 0 ? -1 : 1);
   3423             }
   3424          }
   3425       }
   3426    }
   3427    return winding;
   3428 }
   3429 
   3430 static float stbtt__cuberoot( float x )
   3431 {
   3432    if (x<0)
   3433       return -(float) STBTT_pow(-x,1.0f/3.0f);
   3434    else
   3435       return  (float) STBTT_pow( x,1.0f/3.0f);
   3436 }
   3437 
   3438 // x^3 + c*x^2 + b*x + a = 0
   3439 static int stbtt__solve_cubic(float a, float b, float c, float* r)
   3440 {
   3441 	float s = -a / 3;
   3442 	float p = b - a*a / 3;
   3443 	float q = a * (2*a*a - 9*b) / 27 + c;
   3444    float p3 = p*p*p;
   3445 	float d = q*q + 4*p3 / 27;
   3446 	if (d >= 0) {
   3447 		float z = (float) STBTT_sqrt(d);
   3448 		float u = (-q + z) / 2;
   3449 		float v = (-q - z) / 2;
   3450 		u = stbtt__cuberoot(u);
   3451 		v = stbtt__cuberoot(v);
   3452 		r[0] = s + u + v;
   3453 		return 1;
   3454 	} else {
   3455 	   float u = (float) STBTT_sqrt(-p/3);
   3456 	   float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
   3457 	   float m = (float) STBTT_cos(v);
   3458       float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
   3459 	   r[0] = s + u * 2 * m;
   3460 	   r[1] = s - u * (m + n);
   3461 	   r[2] = s - u * (m - n);
   3462 
   3463       //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f);  // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
   3464       //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
   3465       //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
   3466    	return 3;
   3467    }
   3468 }
   3469 
   3470 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
   3471 {
   3472    float scale_x = scale, scale_y = scale;
   3473    int ix0,iy0,ix1,iy1;
   3474    int w,h;
   3475    unsigned char *data;
   3476 
   3477    if (scale == 0) return NULL;
   3478 
   3479    stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
   3480 
   3481    // if empty, return NULL
   3482    if (ix0 == ix1 || iy0 == iy1)
   3483       return NULL;
   3484 
   3485    ix0 -= padding;
   3486    iy0 -= padding;
   3487    ix1 += padding;
   3488    iy1 += padding;
   3489 
   3490    w = (ix1 - ix0);
   3491    h = (iy1 - iy0);
   3492 
   3493    if (width ) *width  = w;
   3494    if (height) *height = h;
   3495    if (xoff  ) *xoff   = ix0;
   3496    if (yoff  ) *yoff   = iy0;
   3497 
   3498    // invert for y-downwards bitmaps
   3499    scale_y = -scale_y;
   3500 
   3501    {
   3502       int x,y,i,j;
   3503       float *precompute;
   3504       stbtt_vertex *verts;
   3505       int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
   3506       data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
   3507       precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
   3508 
   3509       for (i=0,j=num_verts-1; i < num_verts; j=i++) {
   3510          if (verts[i].type == STBTT_vline) {
   3511             float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
   3512             float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
   3513             float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
   3514             precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
   3515          } else if (verts[i].type == STBTT_vcurve) {
   3516             float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
   3517             float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
   3518             float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
   3519             float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
   3520             float len2 = bx*bx + by*by;
   3521             if (len2 != 0.0f)
   3522                precompute[i] = 1.0f / (bx*bx + by*by);
   3523             else
   3524                precompute[i] = 0.0f;
   3525          } else
   3526             precompute[i] = 0.0f;
   3527       }
   3528 
   3529       for (y=iy0; y < iy1; ++y) {
   3530          for (x=ix0; x < ix1; ++x) {
   3531             float val;
   3532             float min_dist = 999999.0f;
   3533             float sx = (float) x + 0.5f;
   3534             float sy = (float) y + 0.5f;
   3535             float x_gspace = (sx / scale_x);
   3536             float y_gspace = (sy / scale_y);
   3537 
   3538             int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
   3539 
   3540             for (i=0; i < num_verts; ++i) {
   3541                float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
   3542 
   3543                // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
   3544                float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
   3545                if (dist2 < min_dist*min_dist)
   3546                   min_dist = (float) STBTT_sqrt(dist2);
   3547 
   3548                if (verts[i].type == STBTT_vline) {
   3549                   float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
   3550 
   3551                   // coarse culling against bbox
   3552                   //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
   3553                   //    sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
   3554                   float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
   3555                   STBTT_assert(i != 0);
   3556                   if (dist < min_dist) {
   3557                      // check position along line
   3558                      // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
   3559                      // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
   3560                      float dx = x1-x0, dy = y1-y0;
   3561                      float px = x0-sx, py = y0-sy;
   3562                      // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
   3563                      // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
   3564                      float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
   3565                      if (t >= 0.0f && t <= 1.0f)
   3566                         min_dist = dist;
   3567                   }
   3568                } else if (verts[i].type == STBTT_vcurve) {
   3569                   float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
   3570                   float x1 = verts[i  ].cx*scale_x, y1 = verts[i  ].cy*scale_y;
   3571                   float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
   3572                   float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
   3573                   float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
   3574                   float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
   3575                   // coarse culling against bbox to avoid computing cubic unnecessarily
   3576                   if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
   3577                      int num=0;
   3578                      float ax = x1-x0, ay = y1-y0;
   3579                      float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
   3580                      float mx = x0 - sx, my = y0 - sy;
   3581                      float res[3],px,py,t,it;
   3582                      float a_inv = precompute[i];
   3583                      if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
   3584                         float a = 3*(ax*bx + ay*by);
   3585                         float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
   3586                         float c = mx*ax+my*ay;
   3587                         if (a == 0.0) { // if a is 0, it's linear
   3588                            if (b != 0.0) {
   3589                               res[num++] = -c/b;
   3590                            }
   3591                         } else {
   3592                            float discriminant = b*b - 4*a*c;
   3593                            if (discriminant < 0)
   3594                               num = 0;
   3595                            else {
   3596                               float root = (float) STBTT_sqrt(discriminant);
   3597                               res[0] = (-b - root)/(2*a);
   3598                               res[1] = (-b + root)/(2*a);
   3599                               num = 2; // don't bother distinguishing 1-solution case, as code below will still work
   3600                            }
   3601                         }
   3602                      } else {
   3603                         float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
   3604                         float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
   3605                         float d = (mx*ax+my*ay) * a_inv;
   3606                         num = stbtt__solve_cubic(b, c, d, res);
   3607                      }
   3608                      if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
   3609                         t = res[0], it = 1.0f - t;
   3610                         px = it*it*x0 + 2*t*it*x1 + t*t*x2;
   3611                         py = it*it*y0 + 2*t*it*y1 + t*t*y2;
   3612                         dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
   3613                         if (dist2 < min_dist * min_dist)
   3614                            min_dist = (float) STBTT_sqrt(dist2);
   3615                      }
   3616                      if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
   3617                         t = res[1], it = 1.0f - t;
   3618                         px = it*it*x0 + 2*t*it*x1 + t*t*x2;
   3619                         py = it*it*y0 + 2*t*it*y1 + t*t*y2;
   3620                         dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
   3621                         if (dist2 < min_dist * min_dist)
   3622                            min_dist = (float) STBTT_sqrt(dist2);
   3623                      }
   3624                      if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
   3625                         t = res[2], it = 1.0f - t;
   3626                         px = it*it*x0 + 2*t*it*x1 + t*t*x2;
   3627                         py = it*it*y0 + 2*t*it*y1 + t*t*y2;
   3628                         dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
   3629                         if (dist2 < min_dist * min_dist)
   3630                            min_dist = (float) STBTT_sqrt(dist2);
   3631                      }
   3632                   }
   3633                }
   3634             }
   3635             if (winding == 0)
   3636                min_dist = -min_dist;  // if outside the shape, value is negative
   3637             val = onedge_value + pixel_dist_scale * min_dist;
   3638             if (val < 0)
   3639                val = 0;
   3640             else if (val > 255)
   3641                val = 255;
   3642             data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
   3643          }
   3644       }
   3645       STBTT_free(precompute, info->userdata);
   3646       STBTT_free(verts, info->userdata);
   3647    }
   3648    return data;
   3649 }
   3650 
   3651 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
   3652 {
   3653    return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
   3654 }
   3655 
   3656 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
   3657 {
   3658    STBTT_free(bitmap, userdata);
   3659 }
   3660 
   3661 //////////////////////////////////////////////////////////////////////////////
   3662 //
   3663 // font name matching -- recommended not to use this
   3664 //
   3665 
   3666 // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
   3667 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
   3668 {
   3669    stbtt_int32 i=0;
   3670 
   3671    // convert utf16 to utf8 and compare the results while converting
   3672    while (len2) {
   3673       stbtt_uint16 ch = s2[0]*256 + s2[1];
   3674       if (ch < 0x80) {
   3675          if (i >= len1) return -1;
   3676          if (s1[i++] != ch) return -1;
   3677       } else if (ch < 0x800) {
   3678          if (i+1 >= len1) return -1;
   3679          if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
   3680          if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
   3681       } else if (ch >= 0xd800 && ch < 0xdc00) {
   3682          stbtt_uint32 c;
   3683          stbtt_uint16 ch2 = s2[2]*256 + s2[3];
   3684          if (i+3 >= len1) return -1;
   3685          c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
   3686          if (s1[i++] != 0xf0 + (c >> 18)) return -1;
   3687          if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
   3688          if (s1[i++] != 0x80 + ((c >>  6) & 0x3f)) return -1;
   3689          if (s1[i++] != 0x80 + ((c      ) & 0x3f)) return -1;
   3690          s2 += 2; // plus another 2 below
   3691          len2 -= 2;
   3692       } else if (ch >= 0xdc00 && ch < 0xe000) {
   3693          return -1;
   3694       } else {
   3695          if (i+2 >= len1) return -1;
   3696          if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
   3697          if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
   3698          if (s1[i++] != 0x80 + ((ch     ) & 0x3f)) return -1;
   3699       }
   3700       s2 += 2;
   3701       len2 -= 2;
   3702    }
   3703    return i;
   3704 }
   3705 
   3706 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
   3707 {
   3708    return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
   3709 }
   3710 
   3711 // returns results in whatever encoding you request... but note that 2-byte encodings
   3712 // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
   3713 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
   3714 {
   3715    stbtt_int32 i,count,stringOffset;
   3716    stbtt_uint8 *fc = font->data;
   3717    stbtt_uint32 offset = font->fontstart;
   3718    stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
   3719    if (!nm) return NULL;
   3720 
   3721    count = ttUSHORT(fc+nm+2);
   3722    stringOffset = nm + ttUSHORT(fc+nm+4);
   3723    for (i=0; i < count; ++i) {
   3724       stbtt_uint32 loc = nm + 6 + 12 * i;
   3725       if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
   3726           && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
   3727          *length = ttUSHORT(fc+loc+8);
   3728          return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
   3729       }
   3730    }
   3731    return NULL;
   3732 }
   3733 
   3734 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
   3735 {
   3736    stbtt_int32 i;
   3737    stbtt_int32 count = ttUSHORT(fc+nm+2);
   3738    stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
   3739 
   3740    for (i=0; i < count; ++i) {
   3741       stbtt_uint32 loc = nm + 6 + 12 * i;
   3742       stbtt_int32 id = ttUSHORT(fc+loc+6);
   3743       if (id == target_id) {
   3744          // find the encoding
   3745          stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
   3746 
   3747          // is this a Unicode encoding?
   3748          if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
   3749             stbtt_int32 slen = ttUSHORT(fc+loc+8);
   3750             stbtt_int32 off = ttUSHORT(fc+loc+10);
   3751 
   3752             // check if there's a prefix match
   3753             stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
   3754             if (matchlen >= 0) {
   3755                // check for target_id+1 immediately following, with same encoding & language
   3756                if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
   3757                   slen = ttUSHORT(fc+loc+12+8);
   3758                   off = ttUSHORT(fc+loc+12+10);
   3759                   if (slen == 0) {
   3760                      if (matchlen == nlen)
   3761                         return 1;
   3762                   } else if (matchlen < nlen && name[matchlen] == ' ') {
   3763                      ++matchlen;
   3764                      if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
   3765                         return 1;
   3766                   }
   3767                } else {
   3768                   // if nothing immediately following
   3769                   if (matchlen == nlen)
   3770                      return 1;
   3771                }
   3772             }
   3773          }
   3774 
   3775          // @TODO handle other encodings
   3776       }
   3777    }
   3778    return 0;
   3779 }
   3780 
   3781 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
   3782 {
   3783    stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
   3784    stbtt_uint32 nm,hd;
   3785    if (!stbtt__isfont(fc+offset)) return 0;
   3786 
   3787    // check italics/bold/underline flags in macStyle...
   3788    if (flags) {
   3789       hd = stbtt__find_table(fc, offset, "head");
   3790       if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
   3791    }
   3792 
   3793    nm = stbtt__find_table(fc, offset, "name");
   3794    if (!nm) return 0;
   3795 
   3796    if (flags) {
   3797       // if we checked the macStyle flags, then just check the family and ignore the subfamily
   3798       if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))  return 1;
   3799       if (stbtt__matchpair(fc, nm, name, nlen,  1, -1))  return 1;
   3800       if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
   3801    } else {
   3802       if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))  return 1;
   3803       if (stbtt__matchpair(fc, nm, name, nlen,  1,  2))  return 1;
   3804       if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;
   3805    }
   3806 
   3807    return 0;
   3808 }
   3809 
   3810 static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
   3811 {
   3812    stbtt_int32 i;
   3813    for (i=0;;++i) {
   3814       stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
   3815       if (off < 0) return off;
   3816       if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
   3817          return off;
   3818    }
   3819 }
   3820 
   3821 #if defined(__GNUC__) || defined(__clang__)
   3822 #pragma GCC diagnostic push
   3823 #pragma GCC diagnostic ignored "-Wcast-qual"
   3824 #endif
   3825 
   3826 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
   3827                                 float pixel_height, unsigned char *pixels, int pw, int ph,
   3828                                 int first_char, int num_chars, stbtt_bakedchar *chardata)
   3829 {
   3830    return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
   3831 }
   3832 
   3833 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
   3834 {
   3835    return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
   3836 }
   3837 
   3838 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
   3839 {
   3840    return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
   3841 }
   3842 
   3843 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
   3844 {
   3845    return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
   3846 }
   3847 
   3848 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
   3849 {
   3850    return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
   3851 }
   3852 
   3853 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
   3854 {
   3855    return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
   3856 }
   3857 
   3858 #if defined(__GNUC__) || defined(__clang__)
   3859 #pragma GCC diagnostic pop
   3860 #endif
   3861 
   3862 /*
   3863 ------------------------------------------------------------------------------
   3864 This software is available under 2 licenses -- choose whichever you prefer.
   3865 ------------------------------------------------------------------------------
   3866 ALTERNATIVE A - MIT License
   3867 Copyright (c) 2017 Sean Barrett
   3868 Permission is hereby granted, free of charge, to any person obtaining a copy of
   3869 this software and associated documentation files (the "Software"), to deal in
   3870 the Software without restriction, including without limitation the rights to
   3871 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   3872 of the Software, and to permit persons to whom the Software is furnished to do
   3873 so, subject to the following conditions:
   3874 The above copyright notice and this permission notice shall be included in all
   3875 copies or substantial portions of the Software.
   3876 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   3877 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   3878 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   3879 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   3880 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   3881 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   3882 SOFTWARE.
   3883 ------------------------------------------------------------------------------
   3884 ALTERNATIVE B - Public Domain (www.unlicense.org)
   3885 This is free and unencumbered software released into the public domain.
   3886 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
   3887 software, either in source code form or as a compiled binary, for any purpose,
   3888 commercial or non-commercial, and by any means.
   3889 In jurisdictions that recognize copyright laws, the author or authors of this
   3890 software dedicate any and all copyright interest in the software to the public
   3891 domain. We make this dedication for the benefit of the public at large and to
   3892 the detriment of our heirs and successors. We intend this dedication to be an
   3893 overt act of relinquishment in perpetuity of all present and future rights to
   3894 this software under copyright law.
   3895 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   3896 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   3897 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   3898 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   3899 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   3900 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   3901 ------------------------------------------------------------------------------
   3902 */