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