vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

stb_truetype.h (149826B)


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