URI: 
       tUpdate stb_truetype - ltk - Socket-based GUI for X11 (WIP)
  HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 1d97676cf31728fbc5a9dd798da1f6ba1b0f9618
   DIR parent d3b49ae1320664eeb8629e6c50be99642dc7f25e
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Sun, 22 May 2022 21:11:50 +0200
       
       Update stb_truetype
       
       Diffstat:
         M src/stb_truetype.c                  |     686 ++++++++++++++++++-------------
         M src/stb_truetype.h                  |      84 ++++++++++++++++++++++++++++++-
       
       2 files changed, 486 insertions(+), 284 deletions(-)
       ---
   DIR diff --git a/src/stb_truetype.c b/src/stb_truetype.c
       t@@ -1,5 +1,5 @@
       -// stb_truetype.h - v1.24 - public domain
       -// authored from 2009-2020 by Sean Barrett / RAD Game Tools
       +// stb_truetype.h - v1.26 - public domain
       +// authored from 2009-2021 by Sean Barrett / RAD Game Tools
        //
        // =======================================================================
        //
       t@@ -10,8 +10,21 @@
        //
        // =======================================================================
        
       +#include <math.h>
       +#include <stdlib.h>
       +#include <assert.h>
       +#include <string.h>
        #include "stb_truetype.h"
        
       +//////////////////////////////////////////////////////////////////////////////
       +//////////////////////////////////////////////////////////////////////////////
       +////
       +////   INTEGRATION WITH YOUR CODEBASE
       +////
       +////   The following sections allow you to supply alternate definitions
       +////   of C library functions used by stb_truetype, e.g. if you don't
       +////   link with the C runtime library.
       +
        typedef unsigned char   stbtt_uint8;
        typedef signed   char   stbtt_int8;
        typedef unsigned short  stbtt_uint16;
       t@@ -20,27 +33,18 @@ typedef unsigned int    stbtt_uint32;
        typedef signed   int    stbtt_int32;
        typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
        typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
       -#include <math.h>
        #define STBTT_ifloor(x)   ((int) floor(x))
        #define STBTT_iceil(x)    ((int) ceil(x))
       -#include <math.h>
        #define STBTT_sqrt(x)      sqrt(x)
        #define STBTT_pow(x,y)     pow(x,y)
       -#include <math.h>
        #define STBTT_fmod(x,y)    fmod(x,y)
       -#include <math.h>
        #define STBTT_cos(x)       cos(x)
        #define STBTT_acos(x)      acos(x)
       -#include <math.h>
        #define STBTT_fabs(x)      fabs(x)
       -#include <stdlib.h>
        #define STBTT_malloc(x,u)  ((void)(u),malloc(x))
        #define STBTT_free(x,u)    ((void)(u),free(x))
       -#include <assert.h>
        #define STBTT_assert(x)    assert(x)
       -#include <string.h>
        #define STBTT_strlen(x)    strlen(x)
       -#include <string.h>
        #define STBTT_memcpy       memcpy
        #define STBTT_memset       memset
        
       t@@ -490,12 +494,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
              search += 2;
        
              {
       -         stbtt_uint16 offset, start;
       +         stbtt_uint16 offset, start, last;
                 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
        
       -         STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
                 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
       -         if (unicode_codepoint < start)
       +         last = ttUSHORT(data + endCount + 2*item);
       +         if (unicode_codepoint < start || unicode_codepoint > last)
                    return 0;
        
                 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
       t@@ -822,7 +826,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
                       if (comp_verts) STBTT_free(comp_verts, info->userdata);
                       return 0;
                    }
       -            if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
       +            if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
                    STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
                    if (vertices) STBTT_free(vertices, info->userdata);
                    vertices = tmp;
       t@@ -1085,7 +1089,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
                       subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
                    has_subrs = 1;
                 }
       -         // fallthrough
       +         // FALLTHROUGH
              case 0x1D: // callgsubr
                 if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
                 v = (int) s[--sp];
       t@@ -1190,7 +1194,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
              } break;
        
              default:
       -         if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
       +         if (b0 != 255 && b0 != 28 && b0 < 32)
                    return STBTT__CSERR("reserved operator");
        
                 // push immediate
       t@@ -1302,7 +1306,7 @@ STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningent
           return length;
        }
        
       -static int  stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
       +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
        {
           stbtt_uint8 *data = info->data + info->kern;
           stbtt_uint32 needle, straw;
       t@@ -1332,243 +1336,225 @@ static int  stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph
           return 0;
        }
        
       -static stbtt_int32  stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
       -{
       -    stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
       -    switch(coverageFormat) {
       -        case 1: {
       -            stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
       -
       -            // Binary search.
       -            stbtt_int32 l=0, r=glyphCount-1, m;
       -            int straw, needle=glyph;
       -            while (l <= r) {
       -                stbtt_uint8 *glyphArray = coverageTable + 4;
       -                stbtt_uint16 glyphID;
       -                m = (l + r) >> 1;
       -                glyphID = ttUSHORT(glyphArray + 2 * m);
       -                straw = glyphID;
       -                if (needle < straw)
       -                    r = m - 1;
       -                else if (needle > straw)
       -                    l = m + 1;
       -                else {
       -                     return m;
       -                }
       +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
       +{
       +   stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
       +   switch (coverageFormat) {
       +      case 1: {
       +         stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
       +
       +         // Binary search.
       +         stbtt_int32 l=0, r=glyphCount-1, m;
       +         int straw, needle=glyph;
       +         while (l <= r) {
       +            stbtt_uint8 *glyphArray = coverageTable + 4;
       +            stbtt_uint16 glyphID;
       +            m = (l + r) >> 1;
       +            glyphID = ttUSHORT(glyphArray + 2 * m);
       +            straw = glyphID;
       +            if (needle < straw)
       +               r = m - 1;
       +            else if (needle > straw)
       +               l = m + 1;
       +            else {
       +               return m;
                    }
       -        } break;
       -
       -        case 2: {
       -            stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
       -            stbtt_uint8 *rangeArray = coverageTable + 4;
       -
       -            // Binary search.
       -            stbtt_int32 l=0, r=rangeCount-1, m;
       -            int strawStart, strawEnd, needle=glyph;
       -            while (l <= r) {
       -                stbtt_uint8 *rangeRecord;
       -                m = (l + r) >> 1;
       -                rangeRecord = rangeArray + 6 * m;
       -                strawStart = ttUSHORT(rangeRecord);
       -                strawEnd = ttUSHORT(rangeRecord + 2);
       -                if (needle < strawStart)
       -                    r = m - 1;
       -                else if (needle > strawEnd)
       -                    l = m + 1;
       -                else {
       -                    stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
       -                    return startCoverageIndex + glyph - strawStart;
       -                }
       +         }
       +         break;
       +      }
       +
       +      case 2: {
       +         stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
       +         stbtt_uint8 *rangeArray = coverageTable + 4;
       +
       +         // Binary search.
       +         stbtt_int32 l=0, r=rangeCount-1, m;
       +         int strawStart, strawEnd, needle=glyph;
       +         while (l <= r) {
       +            stbtt_uint8 *rangeRecord;
       +            m = (l + r) >> 1;
       +            rangeRecord = rangeArray + 6 * m;
       +            strawStart = ttUSHORT(rangeRecord);
       +            strawEnd = ttUSHORT(rangeRecord + 2);
       +            if (needle < strawStart)
       +               r = m - 1;
       +            else if (needle > strawEnd)
       +               l = m + 1;
       +            else {
       +               stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
       +               return startCoverageIndex + glyph - strawStart;
                    }
       -        } break;
       +         }
       +         break;
       +      }
        
       -        default: {
       -            // There are no other cases.
       -            STBTT_assert(0);
       -        } break;
       -    }
       +      default: return -1; // unsupported
       +   }
        
       -    return -1;
       +   return -1;
        }
        
        static stbtt_int32  stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
        {
       -    stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
       -    switch(classDefFormat)
       -    {
       -        case 1: {
       -            stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
       -            stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
       -            stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
       -
       -            if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
       -                return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
       -
       -            classDefTable = classDef1ValueArray + 2 * glyphCount;
       -        } break;
       -
       -        case 2: {
       -            stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
       -            stbtt_uint8 *classRangeRecords = classDefTable + 4;
       -
       -            // Binary search.
       -            stbtt_int32 l=0, r=classRangeCount-1, m;
       -            int strawStart, strawEnd, needle=glyph;
       -            while (l <= r) {
       -                stbtt_uint8 *classRangeRecord;
       -                m = (l + r) >> 1;
       -                classRangeRecord = classRangeRecords + 6 * m;
       -                strawStart = ttUSHORT(classRangeRecord);
       -                strawEnd = ttUSHORT(classRangeRecord + 2);
       -                if (needle < strawStart)
       -                    r = m - 1;
       -                else if (needle > strawEnd)
       -                    l = m + 1;
       -                else
       -                    return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
       -            }
       +   stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
       +   switch (classDefFormat)
       +   {
       +      case 1: {
       +         stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
       +         stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
       +         stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
        
       -            classDefTable = classRangeRecords + 6 * classRangeCount;
       -        } break;
       +         if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
       +            return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
       +         break;
       +      }
        
       -        default: {
       -            // There are no other cases.
       -            STBTT_assert(0);
       -        } break;
       -    }
       +      case 2: {
       +         stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
       +         stbtt_uint8 *classRangeRecords = classDefTable + 4;
       +
       +         // Binary search.
       +         stbtt_int32 l=0, r=classRangeCount-1, m;
       +         int strawStart, strawEnd, needle=glyph;
       +         while (l <= r) {
       +            stbtt_uint8 *classRangeRecord;
       +            m = (l + r) >> 1;
       +            classRangeRecord = classRangeRecords + 6 * m;
       +            strawStart = ttUSHORT(classRangeRecord);
       +            strawEnd = ttUSHORT(classRangeRecord + 2);
       +            if (needle < strawStart)
       +               r = m - 1;
       +            else if (needle > strawEnd)
       +               l = m + 1;
       +            else
       +               return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
       +         }
       +         break;
       +      }
        
       -    return -1;
       +      default:
       +         return -1; // Unsupported definition type, return an error.
       +   }
       +
       +   // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
       +   return 0;
        }
        
        // Define to STBTT_assert(x) if you want to break on unimplemented formats.
        #define STBTT_GPOS_TODO_assert(x)
        
       -static stbtt_int32  stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
       -{
       -    stbtt_uint16 lookupListOffset;
       -    stbtt_uint8 *lookupList;
       -    stbtt_uint16 lookupCount;
       -    stbtt_uint8 *data;
       -    stbtt_int32 i;
       -
       -    if (!info->gpos) return 0;
       -
       -    data = info->data + info->gpos;
       -
       -    if (ttUSHORT(data+0) != 1) return 0; // Major version 1
       -    if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
       -
       -    lookupListOffset = ttUSHORT(data+8);
       -    lookupList = data + lookupListOffset;
       -    lookupCount = ttUSHORT(lookupList);
       -
       -    for (i=0; i<lookupCount; ++i) {
       -        stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
       -        stbtt_uint8 *lookupTable = lookupList + lookupOffset;
       -
       -        stbtt_uint16 lookupType = ttUSHORT(lookupTable);
       -        stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
       -        stbtt_uint8 *subTableOffsets = lookupTable + 6;
       -        switch(lookupType) {
       -            case 2: { // Pair Adjustment Positioning Subtable
       -                stbtt_int32 sti;
       -                for (sti=0; sti<subTableCount; sti++) {
       -                    stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
       -                    stbtt_uint8 *table = lookupTable + subtableOffset;
       -                    stbtt_uint16 posFormat = ttUSHORT(table);
       -                    stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
       -                    stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
       -                    if (coverageIndex == -1) continue;
       -
       -                    switch (posFormat) {
       -                        case 1: {
       -                            stbtt_int32 l, r, m;
       -                            int straw, needle;
       -                            stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
       -                            stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
       -                            stbtt_int32 valueRecordPairSizeInBytes = 2;
       -                            stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
       -                            stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
       -                            stbtt_uint8 *pairValueTable = table + pairPosOffset;
       -                            stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
       -                            stbtt_uint8 *pairValueArray = pairValueTable + 2;
       -                            // TODO: Support more formats.
       -                            STBTT_GPOS_TODO_assert(valueFormat1 == 4);
       -                            if (valueFormat1 != 4) return 0;
       -                            STBTT_GPOS_TODO_assert(valueFormat2 == 0);
       -                            if (valueFormat2 != 0) return 0;
       -
       -                            STBTT_assert(coverageIndex < pairSetCount);
       -                            STBTT__NOTUSED(pairSetCount);
       -
       -                            needle=glyph2;
       -                            r=pairValueCount-1;
       -                            l=0;
       -
       -                            // Binary search.
       -                            while (l <= r) {
       -                                stbtt_uint16 secondGlyph;
       -                                stbtt_uint8 *pairValue;
       -                                m = (l + r) >> 1;
       -                                pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
       -                                secondGlyph = ttUSHORT(pairValue);
       -                                straw = secondGlyph;
       -                                if (needle < straw)
       -                                    r = m - 1;
       -                                else if (needle > straw)
       -                                    l = m + 1;
       -                                else {
       -                                    stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
       -                                    return xAdvance;
       -                                }
       -                            }
       -                        } break;
       -
       -                        case 2: {
       -                            stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
       -                            stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
       -
       -                            stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
       -                            stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
       -                            int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
       -                            int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
       -
       -                            stbtt_uint16 class1Count = ttUSHORT(table + 12);
       -                            stbtt_uint16 class2Count = ttUSHORT(table + 14);
       -                            STBTT_assert(glyph1class < class1Count);
       -                            STBTT_assert(glyph2class < class2Count);
       -
       -                            // TODO: Support more formats.
       -                            STBTT_GPOS_TODO_assert(valueFormat1 == 4);
       -                            if (valueFormat1 != 4) return 0;
       -                            STBTT_GPOS_TODO_assert(valueFormat2 == 0);
       -                            if (valueFormat2 != 0) return 0;
       -
       -                            if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
       -                                stbtt_uint8 *class1Records = table + 16;
       -                                stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
       -                                stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
       -                                return xAdvance;
       -                            }
       -                        } break;
       -
       -                        default: {
       -                            // There are no other cases.
       -                            STBTT_assert(0);
       -                            break;
       -                        };
       -                    }
       -                }
       -                break;
       -            };
       +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
       +{
       +   stbtt_uint16 lookupListOffset;
       +   stbtt_uint8 *lookupList;
       +   stbtt_uint16 lookupCount;
       +   stbtt_uint8 *data;
       +   stbtt_int32 i, sti;
       +
       +   if (!info->gpos) return 0;
       +
       +   data = info->data + info->gpos;
       +
       +   if (ttUSHORT(data+0) != 1) return 0; // Major version 1
       +   if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
       +
       +   lookupListOffset = ttUSHORT(data+8);
       +   lookupList = data + lookupListOffset;
       +   lookupCount = ttUSHORT(lookupList);
       +
       +   for (i=0; i<lookupCount; ++i) {
       +      stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
       +      stbtt_uint8 *lookupTable = lookupList + lookupOffset;
       +
       +      stbtt_uint16 lookupType = ttUSHORT(lookupTable);
       +      stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
       +      stbtt_uint8 *subTableOffsets = lookupTable + 6;
       +      if (lookupType != 2) // Pair Adjustment Positioning Subtable
       +         continue;
       +
       +      for (sti=0; sti<subTableCount; sti++) {
       +         stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
       +         stbtt_uint8 *table = lookupTable + subtableOffset;
       +         stbtt_uint16 posFormat = ttUSHORT(table);
       +         stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
       +         stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
       +         if (coverageIndex == -1) continue;
       +
       +         switch (posFormat) {
       +            case 1: {
       +               stbtt_int32 l, r, m;
       +               int straw, needle;
       +               stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
       +               stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
       +               if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
       +                  stbtt_int32 valueRecordPairSizeInBytes = 2;
       +                  stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
       +                  stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
       +                  stbtt_uint8 *pairValueTable = table + pairPosOffset;
       +                  stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
       +                  stbtt_uint8 *pairValueArray = pairValueTable + 2;
       +
       +                  if (coverageIndex >= pairSetCount) return 0;
       +
       +                  needle=glyph2;
       +                  r=pairValueCount-1;
       +                  l=0;
       +
       +                  // Binary search.
       +                  while (l <= r) {
       +                     stbtt_uint16 secondGlyph;
       +                     stbtt_uint8 *pairValue;
       +                     m = (l + r) >> 1;
       +                     pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
       +                     secondGlyph = ttUSHORT(pairValue);
       +                     straw = secondGlyph;
       +                     if (needle < straw)
       +                        r = m - 1;
       +                     else if (needle > straw)
       +                        l = m + 1;
       +                     else {
       +                        stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
       +                        return xAdvance;
       +                     }
       +                  }
       +               } else
       +                  return 0;
       +               break;
       +            }
       +
       +            case 2: {
       +               stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
       +               stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
       +               if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
       +                  stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
       +                  stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
       +                  int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
       +                  int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
       +
       +                  stbtt_uint16 class1Count = ttUSHORT(table + 12);
       +                  stbtt_uint16 class2Count = ttUSHORT(table + 14);
       +                  stbtt_uint8 *class1Records, *class2Records;
       +                  stbtt_int16 xAdvance;
       +
       +                  if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
       +                  if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
       +
       +                  class1Records = table + 16;
       +                  class2Records = class1Records + 2 * (glyph1class * class2Count);
       +                  xAdvance = ttSHORT(class2Records + 2 * glyph2class);
       +                  return xAdvance;
       +               } else
       +                  return 0;
       +               break;
       +            }
        
                    default:
       -                // TODO: Implement other stuff.
       -                break;
       -        }
       -    }
       +               return 0; // Unsupported position format
       +         }
       +      }
       +   }
        
       -    return 0;
       +   return 0;
        }
        
        STBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
       t@@ -2026,6 +2012,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg
           }
        }
        
       +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
       +{
       +   STBTT_assert(top_width >= 0);
       +   STBTT_assert(bottom_width >= 0);
       +   return (top_width + bottom_width) / 2.0f * height;
       +}
       +
       +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
       +{
       +   return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
       +}
       +
       +static float stbtt__sized_triangle_area(float height, float width)
       +{
       +   return height * width / 2;
       +}
       +
        static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
        {
           float y_bottom = y_top+1;
       t@@ -2080,13 +2083,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, 
                       float height;
                       // simple case, only spans one pixel
                       int x = (int) x_top;
       -               height = sy1 - sy0;
       +               height = (sy1 - sy0) * e->direction;
                       STBTT_assert(x >= 0 && x < len);
       -               scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2)  * height;
       -               scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
       +               scanline[x]      += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
       +               scanline_fill[x] += height; // everything right of this pixel is filled
                    } else {
                       int x,x1,x2;
       -               float y_crossing, step, sign, area;
       +               float y_crossing, y_final, step, sign, area;
                       // covers 2+ pixels
                       if (x_top > x_bottom) {
                          // flip scanline vertically; signed area is the same
       t@@ -2099,29 +2102,79 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, 
                          dy = -dy;
                          t = x0, x0 = xb, xb = t;
                       }
       +               STBTT_assert(dy >= 0);
       +               STBTT_assert(dx >= 0);
        
                       x1 = (int) x_top;
                       x2 = (int) x_bottom;
                       // compute intersection with y axis at x1+1
       -               y_crossing = (x1+1 - x0) * dy + y_top;
       +               y_crossing = y_top + dy * (x1+1 - x0);
       +
       +               // compute intersection with y axis at x2
       +               y_final = y_top + dy * (x2 - x0);
       +
       +               //           x1    x_top                            x2    x_bottom
       +               //     y_top  +------|-----+------------+------------+--------|---+------------+
       +               //            |            |            |            |            |            |
       +               //            |            |            |            |            |            |
       +               //       sy0  |      Txxxxx|............|............|............|............|
       +               // y_crossing |            *xxxxx.......|............|............|............|
       +               //            |            |     xxxxx..|............|............|............|
       +               //            |            |     /-   xx*xxxx........|............|............|
       +               //            |            | dy <       |    xxxxxx..|............|............|
       +               //   y_final  |            |     \-     |          xx*xxx.........|............|
       +               //       sy1  |            |            |            |   xxxxxB...|............|
       +               //            |            |            |            |            |            |
       +               //            |            |            |            |            |            |
       +               //  y_bottom  +------------+------------+------------+------------+------------+
       +               //
       +               // goal is to measure the area covered by '.' in each pixel
       +
       +               // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
       +               // @TODO: maybe test against sy1 rather than y_bottom?
       +               if (y_crossing > y_bottom)
       +                  y_crossing = y_bottom;
        
                       sign = e->direction;
       -               // area of the rectangle covered from y0..y_crossing
       +
       +               // area of the rectangle covered from sy0..y_crossing
                       area = sign * (y_crossing-sy0);
       -               // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
       -               scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
        
       -               step = sign * dy;
       +               // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
       +               scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
       +
       +               // check if final y_crossing is blown up; no test case for this
       +               if (y_final > y_bottom) {
       +                  y_final = y_bottom;
       +                  dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
       +               }
       +
       +               // in second pixel, area covered by line segment found in first pixel
       +               // is always a rectangle 1 wide * the height of that line segment; this
       +               // is exactly what the variable 'area' stores. it also gets a contribution
       +               // from the line segment within it. the THIRD pixel will get the first
       +               // pixel's rectangle contribution, the second pixel's rectangle contribution,
       +               // and its own contribution. the 'own contribution' is the same in every pixel except
       +               // the leftmost and rightmost, a trapezoid that slides down in each pixel.
       +               // the second pixel's contribution to the third pixel will be the
       +               // rectangle 1 wide times the height change in the second pixel, which is dy.
       +
       +               step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
       +               // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
       +               // so the area advances by 'step' every time
       +
                       for (x = x1+1; x < x2; ++x) {
       -                  scanline[x] += area + step/2;
       +                  scanline[x] += area + step/2; // area of trapezoid is 1*step/2
                          area += step;
                       }
       -               y_crossing += dy * (x2 - (x1+1));
       -
       -               STBTT_assert(STBTT_fabs(area) <= 1.01f);
       +               STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
       +               STBTT_assert(sy1 > y_final-0.01f);
        
       -               scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
       +               // area covered in the last pixel is the rectangle from all the pixels to the left,
       +               // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
       +               scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
        
       +               // the rest of the line is filled based on the total height of the line segment in this pixel
                       scanline_fill[x2] += sign * (sy1-sy0);
                    }
                 } else {
       t@@ -2129,6 +2182,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, 
                    // clipping logic. since this does not match the intended use
                    // of this library, we use a different, very slow brute
                    // force implementation
       +            // note though that this does happen some of the time because
       +            // x_top and x_bottom can be extrapolated at the top & bottom of
       +            // the shape and actually lie outside the bounding box
                    int x;
                    for (x=0; x < len; ++x) {
                       // cases:
       t@@ -3365,15 +3421,14 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
           float y_frac;
           int winding = 0;
        
       -   orig[0] = x;
       -   orig[1] = y;
       -
           // make sure y never passes through a vertex of the shape
           y_frac = (float) STBTT_fmod(y, 1.0f);
           if (y_frac < 0.01f)
              y += 0.01f;
           else if (y_frac > 0.99f)
              y -= 0.01f;
       +
       +   orig[0] = x;
           orig[1] = y;
        
           // test a ray from (-infinity,y) to (x,y)
       t@@ -3435,35 +3490,35 @@ static float stbtt__cuberoot( float x )
              return  (float) STBTT_pow( x,1.0f/3.0f);
        }
        
       -// x^3 + c*x^2 + b*x + a = 0
       +// x^3 + a*x^2 + b*x + c = 0
        static int stbtt__solve_cubic(float a, float b, float c, float* r)
        {
       -        float s = -a / 3;
       -        float p = b - a*a / 3;
       -        float q = a * (2*a*a - 9*b) / 27 + c;
       +   float s = -a / 3;
       +   float p = b - a*a / 3;
       +   float q = a * (2*a*a - 9*b) / 27 + c;
           float p3 = p*p*p;
       -        float d = q*q + 4*p3 / 27;
       -        if (d >= 0) {
       -                float z = (float) STBTT_sqrt(d);
       -                float u = (-q + z) / 2;
       -                float v = (-q - z) / 2;
       -                u = stbtt__cuberoot(u);
       -                v = stbtt__cuberoot(v);
       -                r[0] = s + u + v;
       -                return 1;
       -        } else {
       -           float u = (float) STBTT_sqrt(-p/3);
       -           float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
       -           float m = (float) STBTT_cos(v);
       +   float d = q*q + 4*p3 / 27;
       +   if (d >= 0) {
       +      float z = (float) STBTT_sqrt(d);
       +      float u = (-q + z) / 2;
       +      float v = (-q - z) / 2;
       +      u = stbtt__cuberoot(u);
       +      v = stbtt__cuberoot(v);
       +      r[0] = s + u + v;
       +      return 1;
       +   } else {
       +      float u = (float) STBTT_sqrt(-p/3);
       +      float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
       +      float m = (float) STBTT_cos(v);
              float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
       -           r[0] = s + u * 2 * m;
       -           r[1] = s - u * (m + n);
       -           r[2] = s - u * (m - n);
       +      r[0] = s + u * 2 * m;
       +      r[1] = s - u * (m + n);
       +      r[2] = s - u * (m - n);
        
              //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?
              //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
              //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
       -           return 3;
       +      return 3;
           }
        }
        
       t@@ -3540,18 +3595,17 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
                    for (i=0; i < num_verts; ++i) {
                       float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
        
       -               // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
       -               float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
       -               if (dist2 < min_dist*min_dist)
       -                  min_dist = (float) STBTT_sqrt(dist2);
       -
       -               if (verts[i].type == STBTT_vline) {
       +               if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
                          float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
        
       +                  float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
       +                  if (dist2 < min_dist*min_dist)
       +                     min_dist = (float) STBTT_sqrt(dist2);
       +
                          // coarse culling against bbox
                          //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
                          //    sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
       -                  float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
       +                  dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
                          STBTT_assert(i != 0);
                          if (dist < min_dist) {
                             // check position along line
       t@@ -3578,7 +3632,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
                             float ax = x1-x0, ay = y1-y0;
                             float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
                             float mx = x0 - sx, my = y0 - sy;
       -                     float res[3],px,py,t,it;
       +                     float res[3] = {0.f,0.f,0.f};
       +                     float px,py,t,it,dist2;
                             float a_inv = precompute[i];
                             if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
                                float a = 3*(ax*bx + ay*by);
       t@@ -3605,6 +3660,10 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
                                float d = (mx*ax+my*ay) * a_inv;
                                num = stbtt__solve_cubic(b, c, d, res);
                             }
       +                     dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
       +                     if (dist2 < min_dist*min_dist)
       +                        min_dist = (float) STBTT_sqrt(dist2);
       +
                             if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
                                t = res[0], it = 1.0f - t;
                                px = it*it*x0 + 2*t*it*x1 + t*t*x2;
       t@@ -3859,6 +3918,69 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
        #pragma GCC diagnostic pop
        #endif
        
       +// FULL VERSION HISTORY
       +//
       +//   1.25 (2021-07-11) many fixes
       +//   1.24 (2020-02-05) fix warning
       +//   1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
       +//   1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
       +//   1.21 (2019-02-25) fix warning
       +//   1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
       +//   1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
       +//   1.18 (2018-01-29) add missing function
       +//   1.17 (2017-07-23) make more arguments const; doc fix
       +//   1.16 (2017-07-12) SDF support
       +//   1.15 (2017-03-03) make more arguments const
       +//   1.14 (2017-01-16) num-fonts-in-TTC function
       +//   1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
       +//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
       +//   1.11 (2016-04-02) fix unused-variable warning
       +//   1.10 (2016-04-02) allow user-defined fabs() replacement
       +//                     fix memory leak if fontsize=0.0
       +//                     fix warning from duplicate typedef
       +//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
       +//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
       +//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
       +//                     allow PackFontRanges to pack and render in separate phases;
       +//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
       +//                     fixed an assert() bug in the new rasterizer
       +//                     replace assert() with STBTT_assert() in new rasterizer
       +//   1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
       +//                     also more precise AA rasterizer, except if shapes overlap
       +//                     remove need for STBTT_sort
       +//   1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
       +//   1.04 (2015-04-15) typo in example
       +//   1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
       +//   1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
       +//   1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
       +//                        non-oversampled; STBTT_POINT_SIZE for packed case only
       +//   1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
       +//   0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
       +//   0.9  (2014-08-07) support certain mac/iOS fonts without an MS platformID
       +//   0.8b (2014-07-07) fix a warning
       +//   0.8  (2014-05-25) fix a few more warnings
       +//   0.7  (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
       +//   0.6c (2012-07-24) improve documentation
       +//   0.6b (2012-07-20) fix a few more warnings
       +//   0.6  (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
       +//                        stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
       +//   0.5  (2011-12-09) bugfixes:
       +//                        subpixel glyph renderer computed wrong bounding box
       +//                        first vertex of shape can be off-curve (FreeSans)
       +//   0.4b (2011-12-03) fixed an error in the font baking example
       +//   0.4  (2011-12-01) kerning, subpixel rendering (tor)
       +//                    bugfixes for:
       +//                        codepoint-to-glyph conversion using table fmt=12
       +//                        codepoint-to-glyph conversion using table fmt=4
       +//                        stbtt_GetBakedQuad with non-square texture (Zer)
       +//                    updated Hello World! sample to use kerning and subpixel
       +//                    fixed some warnings
       +//   0.3  (2009-06-24) cmap fmt=12, compound shapes (MM)
       +//                    userdata, malloc-from-userdata, non-zero fill (stb)
       +//   0.2  (2009-03-11) Fix unsigned/signed char warnings
       +//   0.1  (2009-03-09) First public release
       +//
       +
        /*
        ------------------------------------------------------------------------------
        This software is available under 2 licenses -- choose whichever you prefer.
   DIR diff --git a/src/stb_truetype.h b/src/stb_truetype.h
       t@@ -1,5 +1,5 @@
       -// stb_truetype.h - v1.24 - public domain
       -// authored from 2009-2020 by Sean Barrett / RAD Game Tools
       +// stb_truetype.h - v1.26 - public domain
       +// authored from 2009-2021 by Sean Barrett / RAD Game Tools
        //
        // =======================================================================
        //
       t@@ -9,6 +9,85 @@
        // meaning an attacker can use it to read arbitrary memory.
        //
        // =======================================================================
       +//
       +//   This library processes TrueType files:
       +//        parse files
       +//        extract glyph metrics
       +//        extract glyph shapes
       +//        render glyphs to one-channel bitmaps with antialiasing (box filter)
       +//        render glyphs to one-channel SDF bitmaps (signed-distance field/function)
       +//
       +//   Todo:
       +//        non-MS cmaps
       +//        crashproof on bad data
       +//        hinting? (no longer patented)
       +//        cleartype-style AA?
       +//        optimize: use simple memory allocator for intermediates
       +//        optimize: build edge-list directly from curves
       +//        optimize: rasterize directly from curves?
       +//
       +// ADDITIONAL CONTRIBUTORS
       +//
       +//   Mikko Mononen: compound shape support, more cmap formats
       +//   Tor Andersson: kerning, subpixel rendering
       +//   Dougall Johnson: OpenType / Type 2 font handling
       +//   Daniel Ribeiro Maciel: basic GPOS-based kerning
       +//
       +//   Misc other:
       +//       Ryan Gordon
       +//       Simon Glass
       +//       github:IntellectualKitty
       +//       Imanol Celaya
       +//       Daniel Ribeiro Maciel
       +//
       +//   Bug/warning reports/fixes:
       +//       "Zer" on mollyrocket       Fabian "ryg" Giesen   github:NiLuJe
       +//       Cass Everitt               Martins Mozeiko       github:aloucks
       +//       stoiko (Haemimont Games)   Cap Petschulat        github:oyvindjam
       +//       Brian Hook                 Omar Cornut           github:vassvik
       +//       Walter van Niftrik         Ryan Griege
       +//       David Gow                  Peter LaValle
       +//       David Given                Sergey Popov
       +//       Ivan-Assen Ivanov          Giumo X. Clanjor
       +//       Anthony Pesch              Higor Euripedes
       +//       Johan Duparc               Thomas Fields
       +//       Hou Qiming                 Derek Vinyard
       +//       Rob Loach                  Cort Stratton
       +//       Kenney Phillis Jr.         Brian Costabile
       +//       Ken Voskuil (kaesve)
       +//
       +// VERSION HISTORY
       +//
       +//   1.26 (2021-08-28) fix broken rasterizer
       +//   1.25 (2021-07-11) many fixes
       +//   1.24 (2020-02-05) fix warning
       +//   1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
       +//   1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
       +//   1.21 (2019-02-25) fix warning
       +//   1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
       +//   1.19 (2018-02-11) GPOS kerning, STBTT_fmod
       +//   1.18 (2018-01-29) add missing function
       +//   1.17 (2017-07-23) make more arguments const; doc fix
       +//   1.16 (2017-07-12) SDF support
       +//   1.15 (2017-03-03) make more arguments const
       +//   1.14 (2017-01-16) num-fonts-in-TTC function
       +//   1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
       +//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
       +//   1.11 (2016-04-02) fix unused-variable warning
       +//   1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
       +//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
       +//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
       +//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
       +//                     variant PackFontRanges to pack and render in separate phases;
       +//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
       +//                     fixed an assert() bug in the new rasterizer
       +//                     replace assert() with STBTT_assert() in new rasterizer
       +//
       +//   Full history can be found at the end of this file.
       +//
       +// LICENSE
       +//
       +//   See end of file for license information.
        
        ///////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////
       t@@ -378,6 +457,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
        STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
        // frees the data allocated above
        
       +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
        STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
        STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
        // fills svg with the character's SVG data.