vtgl

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

stb_truetype.h (174511B)


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