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