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