cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

imstb_truetype.h (192490B)


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