vtgl

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

stb_truetype.h (149616B)


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