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