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