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