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