ltk

Socket-based GUI for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

stb_truetype.c (149573B)


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