SayoriOS 0.3.3

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