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