XenevaOS
Loading...
Searching...
No Matches
stb_truetype.h
Go to the documentation of this file.
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) Yakov Galka
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
269#define STB_TRYETYPE_IMPLEMENTATION 1
275//
276// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
277// See "tests/truetype_demo_win32.c" for a complete version.
278#if 0
279#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
280#include "stb_truetype.h"
281
282unsigned char ttf_buffer[1 << 20];
283unsigned char temp_bitmap[512 * 512];
284
285stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
286GLuint ftex;
287
288void my_stbtt_initfont(void)
289{
290 fread(ttf_buffer, 1, 1 << 20, fopen("c:/windows/fonts/times.ttf", "rb"));
291 stbtt_BakeFontBitmap(ttf_buffer, 0, 32.0, temp_bitmap, 512, 512, 32, 96, cdata); // no guarantee this fits!
292 // can free ttf_buffer at this point
293 glGenTextures(1, &ftex);
294 glBindTexture(GL_TEXTURE_2D, ftex);
295 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512, 512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
296 // can free temp_bitmap at this point
297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
298}
299
300void my_stbtt_print(float x, float y, char* text)
301{
302 // assume orthographic projection with units = screen pixels, origin at top left
303 glEnable(GL_BLEND);
304 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
305 glEnable(GL_TEXTURE_2D);
306 glBindTexture(GL_TEXTURE_2D, ftex);
307 glBegin(GL_QUADS);
308 while (*text) {
309 if (*text >= 32 && *text < 128) {
311 stbtt_GetBakedQuad(cdata, 512, 512, *text - 32, &x, &y, &q, 1);//1=opengl & d3d10+,0=d3d9
312 glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
313 glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
314 glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
315 glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
316 }
317 ++text;
318 }
319 glEnd();
320}
321#endif
322//
323//
325//
326// Complete program (this compiles): get a single bitmap, print as ASCII art
327//
328#if 0
329#include <stdio.h>
330#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
331#include "stb_truetype.h"
332
333char ttf_buffer[1 << 25];
334
335int main(int argc, char** argv)
336{
337 stbtt_fontinfo font;
338 unsigned char* bitmap;
339 int w, h, i, j, c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
340
341 fread(ttf_buffer, 1, 1 << 25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
342
343 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer, 0));
344 bitmap = stbtt_GetCodepointBitmap(&font, 0, stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0, 0);
345
346 for (j = 0; j < h; ++j) {
347 for (i = 0; i < w; ++i)
348 putchar(" .:ioVM@"[bitmap[j * w + i] >> 5]);
349 putchar('\n');
350 }
351 return 0;
352}
353#endif
354//
355// Output:
356//
357// .ii.
358// @@@@@@.
359// V@Mio@@o
360// :i. V@V
361// :oM@@M
362// :@@@MM@M
363// @@o o@M
364// :@@. M@M
365// @@@o@@@@
366// :M@@V:@@.
367//
369//
370// Complete program: print "Hello World!" banner, with bugs
371//
372#if 0
373char buffer[24 << 20];
374unsigned char screen[20][79];
375
376int main(int arg, char** argv)
377{
378 stbtt_fontinfo font;
379 int i, j, ascent, baseline, ch = 0;
380 float scale, xpos = 2; // leave a little padding in case the character extends left
381 char* text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
382
383 fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
384 stbtt_InitFont(&font, buffer, 0);
385
386 scale = stbtt_ScaleForPixelHeight(&font, 15);
387 stbtt_GetFontVMetrics(&font, &ascent, 0, 0);
388 baseline = (int)(ascent * scale);
389
390 while (text[ch]) {
391 int advance, lsb, x0, y0, x1, y1;
392 float x_shift = xpos - (float)floor(xpos);
393 stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
394 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale, scale, x_shift, 0, &x0, &y0, &x1, &y1);
395 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int)xpos + x0], x1 - x0, y1 - y0, 79, scale, scale, x_shift, 0, text[ch]);
396 // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
397 // because this API is really for baking character bitmaps into textures. if you want to render
398 // a sequence of characters, you really need to render each bitmap to a temp buffer, then
399 // "alpha blend" that into the working buffer
400 xpos += (advance * scale);
401 if (text[ch + 1])
402 xpos += scale * stbtt_GetCodepointKernAdvance(&font, text[ch], text[ch + 1]);
403 ++ch;
404 }
405
406 for (j = 0; j < 20; ++j) {
407 for (i = 0; i < 78; ++i)
408 putchar(" .:ioVM@"[screen[j][i] >> 5]);
409 putchar('\n');
410 }
411
412 return 0;
413}
414#endif
415
416
425
426#ifdef STB_TRUETYPE_IMPLEMENTATION
427 // #define your own (u)stbtt_int8/16/32 before including to override this
428#ifndef stbtt_uint8
429typedef unsigned char stbtt_uint8;
430typedef signed char stbtt_int8;
431typedef unsigned short stbtt_uint16;
432typedef signed short stbtt_int16;
433typedef unsigned int stbtt_uint32;
434typedef signed int stbtt_int32;
435#endif
436
437typedef char stbtt__check_size32[sizeof(stbtt_int32) == 4 ? 1 : -1];
438typedef char stbtt__check_size16[sizeof(stbtt_int16) == 2 ? 1 : -1];
439
440// e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
441#ifndef STBTT_ifloor
442#include <math.h>
443#define STBTT_ifloor(x) ((int) floor(x))
444#define STBTT_iceil(x) ((int) ceil(x))
445#endif
446
447#ifndef STBTT_sqrt
448#include <math.h>
449#define STBTT_sqrt(x) sqrt(x)
450#define STBTT_pow(x,y) pow(x,y)
451#endif
452
453#ifndef STBTT_fmod
454#include <math.h>
455#define STBTT_fmod(x,y) fmod(x,y)
456#endif
457
458#ifndef STBTT_cos
459#include <math.h>
460#define STBTT_cos(x) cos(x)
461#define STBTT_acos(x) acos(x)
462#endif
463
464#ifndef STBTT_fabs
465#include <math.h>
466#define STBTT_fabs(x) fabs(x)
467#endif
468
469// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
470#ifndef STBTT_malloc
471#include <stdlib.h>
472#define STBTT_malloc(x,u) ((void)(u),malloc(x))
473#define STBTT_free(x,u) ((void)(u),free(x))
474#endif
475
476#ifndef STBTT_assert
477#include <assert.h>
478#define STBTT_assert(x) assert(x)
479#endif
480
481#ifndef STBTT_strlen
482#include <string.h>
483#define STBTT_strlen(x) strlen(x)
484#endif
485
486#ifndef STBTT_memcpy
487#include <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
510extern "C" {
511#endif
512
513 // private structure
514 typedef struct
515 {
516 unsigned char* data;
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;
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
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;
582
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
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 {
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
627 unsigned char h_oversample, v_oversample; // don't set these, they're used internally
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
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
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.
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.
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
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
811
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 {
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
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;
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
1051
1052 enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
1059
1060 enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
1066
1067 enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
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
1083
1084 enum { // languageID for STBTT_PLATFORM_ID_MAC
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
1117typedef 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
1134static 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
1141static 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
1148static 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
1154static void stbtt__buf_skip(stbtt__buf* b, int o)
1155{
1156 stbtt__buf_seek(b, b->cursor + o);
1157}
1158
1159static 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
1169static 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
1182static 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
1191static 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
1205static 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
1217static 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 }
1228 else {
1229 stbtt__cff_int(b);
1230 }
1231}
1232
1233static stbtt__buf stbtt__dict_get(stbtt__buf* b, int key)
1234{
1235 stbtt__buf_seek(b, 0);
1236 while (b->cursor < b->size) {
1237 int start = b->cursor, end, op;
1238 while (stbtt__buf_peek8(b) >= 28)
1239 stbtt__cff_skip_operand(b);
1240 end = b->cursor;
1241 op = stbtt__buf_get8(b);
1242 if (op == 12) op = stbtt__buf_get8(b) | 0x100;
1243 if (op == key) return stbtt__buf_range(b, start, end - start);
1244 }
1245 return stbtt__buf_range(b, 0, 0);
1246}
1247
1248static void stbtt__dict_get_ints(stbtt__buf* b, int key, int outcount, stbtt_uint32* out)
1249{
1250 int i;
1251 stbtt__buf operands = stbtt__dict_get(b, key);
1252 for (i = 0; i < outcount && operands.cursor < operands.size; i++)
1253 out[i] = stbtt__cff_int(&operands);
1254}
1255
1256static int stbtt__cff_index_count(stbtt__buf* b)
1257{
1258 stbtt__buf_seek(b, 0);
1259 return stbtt__buf_get16(b);
1260}
1261
1262static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
1263{
1264 int count, offsize, start, end;
1265 stbtt__buf_seek(&b, 0);
1266 count = stbtt__buf_get16(&b);
1267 offsize = stbtt__buf_get8(&b);
1268 STBTT_assert(i >= 0 && i < count);
1269 STBTT_assert(offsize >= 1 && offsize <= 4);
1270 stbtt__buf_skip(&b, i * offsize);
1271 start = stbtt__buf_get(&b, offsize);
1272 end = stbtt__buf_get(&b, offsize);
1273 return stbtt__buf_range(&b, 2 + (count + 1) * offsize + start, end - start);
1274}
1275
1277//
1278// accessors to parse data from file
1279//
1280
1281// on platforms that don't allow misaligned reads, if we want to allow
1282// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
1283
1284#define ttBYTE(p) (* (stbtt_uint8 *) (p))
1285#define ttCHAR(p) (* (stbtt_int8 *) (p))
1286#define ttFixed(p) ttLONG(p)
1287
1288static stbtt_uint16 ttUSHORT(stbtt_uint8* p) { return p[0] * 256 + p[1]; }
1289static stbtt_int16 ttSHORT(stbtt_uint8* p) { return p[0] * 256 + p[1]; }
1290static stbtt_uint32 ttULONG(stbtt_uint8* p) { return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; }
1291static stbtt_int32 ttLONG(stbtt_uint8* p) { return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; }
1292
1293#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
1294#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
1295
1296static int stbtt__isfont(stbtt_uint8* font)
1297{
1298 // check the version number
1299 if (stbtt_tag4(font, '1', 0, 0, 0)) return 1; // TrueType 1
1300 if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
1301 if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
1302 if (stbtt_tag4(font, 0, 1, 0, 0)) return 1; // OpenType 1.0
1303 if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
1304 return 0;
1305}
1306
1307// @OPTIMIZE: binary search
1308static stbtt_uint32 stbtt__find_table(stbtt_uint8* data, stbtt_uint32 fontstart, const char* tag)
1309{
1310 stbtt_int32 num_tables = ttUSHORT(data + fontstart + 4);
1311 stbtt_uint32 tabledir = fontstart + 12;
1312 stbtt_int32 i;
1313 for (i = 0; i < num_tables; ++i) {
1314 stbtt_uint32 loc = tabledir + 16 * i;
1315 if (stbtt_tag(data + loc + 0, tag))
1316 return ttULONG(data + loc + 8);
1317 }
1318 return 0;
1319}
1320
1321static int stbtt_GetFontOffsetForIndex_internal(unsigned char* font_collection, int index)
1322{
1323 // if it's just a font, there's only one valid index
1324 if (stbtt__isfont(font_collection))
1325 return index == 0 ? 0 : -1;
1326
1327 // check if it's a TTC
1328 if (stbtt_tag(font_collection, "ttcf")) {
1329 // version 1?
1330 if (ttULONG(font_collection + 4) == 0x00010000 || ttULONG(font_collection + 4) == 0x00020000) {
1331 stbtt_int32 n = ttLONG(font_collection + 8);
1332 if (index >= n)
1333 return -1;
1334 return ttULONG(font_collection + 12 + index * 4);
1335 }
1336 }
1337 return -1;
1338}
1339
1340static int stbtt_GetNumberOfFonts_internal(unsigned char* font_collection)
1341{
1342 // if it's just a font, there's only one valid font
1343 if (stbtt__isfont(font_collection))
1344 return 1;
1345
1346 // check if it's a TTC
1347 if (stbtt_tag(font_collection, "ttcf")) {
1348 // version 1?
1349 if (ttULONG(font_collection + 4) == 0x00010000 || ttULONG(font_collection + 4) == 0x00020000) {
1350 return ttLONG(font_collection + 8);
1351 }
1352 }
1353 return 0;
1354}
1355
1356static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
1357{
1358 stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
1359 stbtt__buf pdict;
1360 stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
1361 if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
1362 pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
1363 stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
1364 if (!subrsoff) return stbtt__new_buf(NULL, 0);
1365 stbtt__buf_seek(&cff, private_loc[1] + subrsoff);
1366 return stbtt__cff_get_index(&cff);
1367}
1368
1369// since most people won't use this, find this table the first time it's needed
1370static int stbtt__get_svg(stbtt_fontinfo* info)
1371{
1372 stbtt_uint32 t;
1373 if (info->svg < 0) {
1374 t = stbtt__find_table(info->data, info->fontstart, "SVG ");
1375 if (t) {
1376 stbtt_uint32 offset = ttULONG(info->data + t + 2);
1377 info->svg = t + offset;
1378 }
1379 else {
1380 info->svg = 0;
1381 }
1382 }
1383 return info->svg;
1384}
1385
1386static int stbtt_InitFont_internal(stbtt_fontinfo* info, unsigned char* data, int fontstart)
1387{
1388 stbtt_uint32 cmap, t;
1389 stbtt_int32 i, numTables;
1390
1391 info->data = data;
1392 info->fontstart = fontstart;
1393 info->cff = stbtt__new_buf(NULL, 0);
1394
1395 cmap = stbtt__find_table(data, fontstart, "cmap"); // required
1396 info->loca = stbtt__find_table(data, fontstart, "loca"); // required
1397 info->head = stbtt__find_table(data, fontstart, "head"); // required
1398 info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
1399 info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
1400 info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
1401 info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
1402 info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
1403
1404 if (!cmap || !info->head || !info->hhea || !info->hmtx)
1405 return 0;
1406 if (info->glyf) {
1407 // required for truetype
1408 if (!info->loca) return 0;
1409 }
1410 else {
1411 // initialization for CFF / Type2 fonts (OTF)
1412 stbtt__buf b, topdict, topdictidx;
1413 stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
1414 stbtt_uint32 cff;
1415
1416 cff = stbtt__find_table(data, fontstart, "CFF ");
1417 if (!cff) return 0;
1418
1419 info->fontdicts = stbtt__new_buf(NULL, 0);
1420 info->fdselect = stbtt__new_buf(NULL, 0);
1421
1422 // @TODO this should use size from table (not 512MB)
1423 info->cff = stbtt__new_buf(data + cff, 512 * 1024 * 1024);
1424 b = info->cff;
1425
1426 // read the header
1427 stbtt__buf_skip(&b, 2);
1428 stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
1429
1430 // @TODO the name INDEX could list multiple fonts,
1431 // but we just use the first one.
1432 stbtt__cff_get_index(&b); // name INDEX
1433 topdictidx = stbtt__cff_get_index(&b);
1434 topdict = stbtt__cff_index_get(topdictidx, 0);
1435 stbtt__cff_get_index(&b); // string INDEX
1436 info->gsubrs = stbtt__cff_get_index(&b);
1437
1438 stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
1439 stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
1440 stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
1441 stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
1442 info->subrs = stbtt__get_subrs(b, topdict);
1443
1444 // we only support Type 2 charstrings
1445 if (cstype != 2) return 0;
1446 if (charstrings == 0) return 0;
1447
1448 if (fdarrayoff) {
1449 // looks like a CID font
1450 if (!fdselectoff) return 0;
1451 stbtt__buf_seek(&b, fdarrayoff);
1452 info->fontdicts = stbtt__cff_get_index(&b);
1453 info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size - fdselectoff);
1454 }
1455
1456 stbtt__buf_seek(&b, charstrings);
1457 info->charstrings = stbtt__cff_get_index(&b);
1458 }
1459
1460 t = stbtt__find_table(data, fontstart, "maxp");
1461 if (t)
1462 info->numGlyphs = ttUSHORT(data + t + 4);
1463 else
1464 info->numGlyphs = 0xffff;
1465
1466 info->svg = -1;
1467
1468 // find a cmap encoding table we understand *now* to avoid searching
1469 // later. (todo: could make this installable)
1470 // the same regardless of glyph.
1471 numTables = ttUSHORT(data + cmap + 2);
1472 info->index_map = 0;
1473 for (i = 0; i < numTables; ++i) {
1474 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1475 // find an encoding we understand:
1476 switch (ttUSHORT(data + encoding_record)) {
1478 switch (ttUSHORT(data + encoding_record + 2)) {
1481 // MS/Unicode
1482 info->index_map = cmap + ttULONG(data + encoding_record + 4);
1483 break;
1484 }
1485 break;
1487 // Mac/iOS has these
1488 // all the encodingIDs are unicode, so we don't bother to check it
1489 info->index_map = cmap + ttULONG(data + encoding_record + 4);
1490 break;
1491 }
1492 }
1493 if (info->index_map == 0)
1494 return 0;
1495
1496 info->indexToLocFormat = ttUSHORT(data + info->head + 50);
1497 return 1;
1498}
1499
1500STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo* info, int unicode_codepoint)
1501{
1502 stbtt_uint8* data = info->data;
1503 stbtt_uint32 index_map = info->index_map;
1504
1505 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1506 if (format == 0) { // apple byte encoding
1507 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1508 if (unicode_codepoint < bytes - 6)
1509 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1510 return 0;
1511 }
1512 else if (format == 6) {
1513 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1514 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1515 if ((stbtt_uint32)unicode_codepoint >= first && (stbtt_uint32)unicode_codepoint < first + count)
1516 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first) * 2);
1517 return 0;
1518 }
1519 else if (format == 2) {
1520 STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
1521 return 0;
1522 }
1523 else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
1524 stbtt_uint16 segcount = ttUSHORT(data + index_map + 6) >> 1;
1525 stbtt_uint16 searchRange = ttUSHORT(data + index_map + 8) >> 1;
1526 stbtt_uint16 entrySelector = ttUSHORT(data + index_map + 10);
1527 stbtt_uint16 rangeShift = ttUSHORT(data + index_map + 12) >> 1;
1528
1529 // do a binary search of the segments
1530 stbtt_uint32 endCount = index_map + 14;
1531 stbtt_uint32 search = endCount;
1532
1533 if (unicode_codepoint > 0xffff)
1534 return 0;
1535
1536 // they lie from endCount .. endCount + segCount
1537 // but searchRange is the nearest power of two, so...
1538 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift * 2))
1539 search += rangeShift * 2;
1540
1541 // now decrement to bias correctly to find smallest
1542 search -= 2;
1543 while (entrySelector) {
1544 stbtt_uint16 end;
1545 searchRange >>= 1;
1546 end = ttUSHORT(data + search + searchRange * 2);
1547 if (unicode_codepoint > end)
1548 search += searchRange * 2;
1549 --entrySelector;
1550 }
1551 search += 2;
1552
1553 {
1554 stbtt_uint16 offset, start, last;
1555 stbtt_uint16 item = (stbtt_uint16)((search - endCount) >> 1);
1556
1557 start = ttUSHORT(data + index_map + 14 + segcount * 2 + 2 + 2 * item);
1558 last = ttUSHORT(data + endCount + 2 * item);
1559 if (unicode_codepoint < start || unicode_codepoint > last)
1560 return 0;
1561
1562 offset = ttUSHORT(data + index_map + 14 + segcount * 6 + 2 + 2 * item);
1563 if (offset == 0)
1564 return (stbtt_uint16)(unicode_codepoint + ttSHORT(data + index_map + 14 + segcount * 4 + 2 + 2 * item));
1565
1566 return ttUSHORT(data + offset + (unicode_codepoint - start) * 2 + index_map + 14 + segcount * 6 + 2 + 2 * item);
1567 }
1568 }
1569 else if (format == 12 || format == 13) {
1570 stbtt_uint32 ngroups = ttULONG(data + index_map + 12);
1571 stbtt_int32 low, high;
1572 low = 0; high = (stbtt_int32)ngroups;
1573 // Binary search the right group.
1574 while (low < high) {
1575 stbtt_int32 mid = low + ((high - low) >> 1); // rounds down, so low <= mid < high
1576 stbtt_uint32 start_char = ttULONG(data + index_map + 16 + mid * 12);
1577 stbtt_uint32 end_char = ttULONG(data + index_map + 16 + mid * 12 + 4);
1578 if ((stbtt_uint32)unicode_codepoint < start_char)
1579 high = mid;
1580 else if ((stbtt_uint32)unicode_codepoint > end_char)
1581 low = mid + 1;
1582 else {
1583 stbtt_uint32 start_glyph = ttULONG(data + index_map + 16 + mid * 12 + 8);
1584 if (format == 12)
1585 return start_glyph + unicode_codepoint - start_char;
1586 else // format == 13
1587 return start_glyph;
1588 }
1589 }
1590 return 0; // not found
1591 }
1592 // @TODO
1593 STBTT_assert(0);
1594 return 0;
1595}
1596
1597STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo* info, int unicode_codepoint, stbtt_vertex** vertices)
1598{
1599 return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
1600}
1601
1602static void stbtt_setvertex(stbtt_vertex* v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1603{
1604 v->type = type;
1605 v->x = (stbtt_int16)x;
1606 v->y = (stbtt_int16)y;
1607 v->cx = (stbtt_int16)cx;
1608 v->cy = (stbtt_int16)cy;
1609}
1610
1611static int stbtt__GetGlyfOffset(const stbtt_fontinfo* info, int glyph_index)
1612{
1613 int g1, g2;
1614
1615 STBTT_assert(!info->cff.size);
1616
1617 if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
1618 if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
1619
1620 if (info->indexToLocFormat == 0) {
1621 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
1622 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
1623 }
1624 else {
1625 g1 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4);
1626 g2 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4 + 4);
1627 }
1628
1629 return g1 == g2 ? -1 : g1; // if length is 0, return -1
1630}
1631
1632static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo* info, int glyph_index, int* x0, int* y0, int* x1, int* y1);
1633
1634STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo* info, int glyph_index, int* x0, int* y0, int* x1, int* y1)
1635{
1636 if (info->cff.size) {
1637 stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
1638 }
1639 else {
1640 int g = stbtt__GetGlyfOffset(info, glyph_index);
1641 if (g < 0) return 0;
1642
1643 if (x0) *x0 = ttSHORT(info->data + g + 2);
1644 if (y0) *y0 = ttSHORT(info->data + g + 4);
1645 if (x1) *x1 = ttSHORT(info->data + g + 6);
1646 if (y1) *y1 = ttSHORT(info->data + g + 8);
1647 }
1648 return 1;
1649}
1650
1651STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo* info, int codepoint, int* x0, int* y0, int* x1, int* y1)
1652{
1653 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info, codepoint), x0, y0, x1, y1);
1654}
1655
1656STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo* info, int glyph_index)
1657{
1658 stbtt_int16 numberOfContours;
1659 int g;
1660 if (info->cff.size)
1661 return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
1662 g = stbtt__GetGlyfOffset(info, glyph_index);
1663 if (g < 0) return 1;
1664 numberOfContours = ttSHORT(info->data + g);
1665 return numberOfContours == 0;
1666}
1667
1668static int stbtt__close_shape(stbtt_vertex* vertices, int num_vertices, int was_off, int start_off,
1669 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1670{
1671 if (start_off) {
1672 if (was_off)
1673 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx + scx) >> 1, (cy + scy) >> 1, cx, cy);
1674 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, scx, scy);
1675 }
1676 else {
1677 if (was_off)
1678 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, cx, cy);
1679 else
1680 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, sx, sy, 0, 0);
1681 }
1682 return num_vertices;
1683}
1684
1685static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo* info, int glyph_index, stbtt_vertex** pvertices)
1686{
1687 stbtt_int16 numberOfContours;
1688 stbtt_uint8* endPtsOfContours;
1689 stbtt_uint8* data = info->data;
1690 stbtt_vertex* vertices = 0;
1691 int num_vertices = 0;
1692 int g = stbtt__GetGlyfOffset(info, glyph_index);
1693
1694 *pvertices = NULL;
1695
1696 if (g < 0) return 0;
1697
1698 numberOfContours = ttSHORT(data + g);
1699
1700 if (numberOfContours > 0) {
1701 stbtt_uint8 flags = 0, flagcount;
1702 stbtt_int32 ins, i, j = 0, m, n, next_move, was_off = 0, off, start_off = 0;
1703 stbtt_int32 x, y, cx, cy, sx, sy, scx, scy;
1704 stbtt_uint8* points;
1705 endPtsOfContours = (data + g + 10);
1706 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1707 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1708
1709 n = 1 + ttUSHORT(endPtsOfContours + numberOfContours * 2 - 2);
1710
1711 m = n + 2 * numberOfContours; // a loose bound on how many vertices we might need
1712 vertices = (stbtt_vertex*)STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
1713 if (vertices == 0)
1714 return 0;
1715
1716 next_move = 0;
1717 flagcount = 0;
1718
1719 // in first pass, we load uninterpreted data into the allocated array
1720 // above, shifted to the end of the array so we won't overwrite it when
1721 // we create our final data starting from the front
1722
1723 off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
1724
1725 // first load flags
1726
1727 for (i = 0; i < n; ++i) {
1728 if (flagcount == 0) {
1729 flags = *points++;
1730 if (flags & 8)
1731 flagcount = *points++;
1732 }
1733 else
1734 --flagcount;
1735 vertices[off + i].type = flags;
1736 }
1737
1738 // now load x coordinates
1739 x = 0;
1740 for (i = 0; i < n; ++i) {
1741 flags = vertices[off + i].type;
1742 if (flags & 2) {
1743 stbtt_int16 dx = *points++;
1744 x += (flags & 16) ? dx : -dx; // ???
1745 }
1746 else {
1747 if (!(flags & 16)) {
1748 x = x + (stbtt_int16)(points[0] * 256 + points[1]);
1749 points += 2;
1750 }
1751 }
1752 vertices[off + i].x = (stbtt_int16)x;
1753 }
1754
1755 // now load y coordinates
1756 y = 0;
1757 for (i = 0; i < n; ++i) {
1758 flags = vertices[off + i].type;
1759 if (flags & 4) {
1760 stbtt_int16 dy = *points++;
1761 y += (flags & 32) ? dy : -dy; // ???
1762 }
1763 else {
1764 if (!(flags & 32)) {
1765 y = y + (stbtt_int16)(points[0] * 256 + points[1]);
1766 points += 2;
1767 }
1768 }
1769 vertices[off + i].y = (stbtt_int16)y;
1770 }
1771
1772 // now convert them to our format
1773 num_vertices = 0;
1774 sx = sy = cx = cy = scx = scy = 0;
1775 for (i = 0; i < n; ++i) {
1776 flags = vertices[off + i].type;
1777 x = (stbtt_int16)vertices[off + i].x;
1778 y = (stbtt_int16)vertices[off + i].y;
1779
1780 if (next_move == i) {
1781 if (i != 0)
1782 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx, sy, scx, scy, cx, cy);
1783
1784 // now start the new one
1785 start_off = !(flags & 1);
1786 if (start_off) {
1787 // if we start off with an off-curve point, then when we need to find a point on the curve
1788 // where we can start, and we need to save some state for when we wraparound.
1789 scx = x;
1790 scy = y;
1791 if (!(vertices[off + i + 1].type & 1)) {
1792 // next point is also a curve point, so interpolate an on-point curve
1793 sx = (x + (stbtt_int32)vertices[off + i + 1].x) >> 1;
1794 sy = (y + (stbtt_int32)vertices[off + i + 1].y) >> 1;
1795 }
1796 else {
1797 // otherwise just use the next point as our start point
1798 sx = (stbtt_int32)vertices[off + i + 1].x;
1799 sy = (stbtt_int32)vertices[off + i + 1].y;
1800 ++i; // we're using point i+1 as the starting point, so skip it
1801 }
1802 }
1803 else {
1804 sx = x;
1805 sy = y;
1806 }
1807 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove, sx, sy, 0, 0);
1808 was_off = 0;
1809 next_move = 1 + ttUSHORT(endPtsOfContours + j * 2);
1810 ++j;
1811 }
1812 else {
1813 if (!(flags & 1)) { // if it's a curve
1814 if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
1815 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx + x) >> 1, (cy + y) >> 1, cx, cy);
1816 cx = x;
1817 cy = y;
1818 was_off = 1;
1819 }
1820 else {
1821 if (was_off)
1822 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x, y, cx, cy);
1823 else
1824 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x, y, 0, 0);
1825 was_off = 0;
1826 }
1827 }
1828 }
1829 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx, sy, scx, scy, cx, cy);
1830 }
1831 else if (numberOfContours < 0) {
1832 // Compound shapes.
1833 int more = 1;
1834 stbtt_uint8* comp = data + g + 10;
1835 num_vertices = 0;
1836 vertices = 0;
1837 while (more) {
1838 stbtt_uint16 flags, gidx;
1839 int comp_num_verts = 0, i;
1840 stbtt_vertex* comp_verts = 0, * tmp = 0;
1841 float mtx[6] = { 1,0,0,1,0,0 }, m, n;
1842
1843 flags = ttSHORT(comp); comp += 2;
1844 gidx = ttSHORT(comp); comp += 2;
1845
1846 if (flags & 2) { // XY values
1847 if (flags & 1) { // shorts
1848 mtx[4] = ttSHORT(comp); comp += 2;
1849 mtx[5] = ttSHORT(comp); comp += 2;
1850 }
1851 else {
1852 mtx[4] = ttCHAR(comp); comp += 1;
1853 mtx[5] = ttCHAR(comp); comp += 1;
1854 }
1855 }
1856 else {
1857 // @TODO handle matching point
1858 STBTT_assert(0);
1859 }
1860 if (flags & (1 << 3)) { // WE_HAVE_A_SCALE
1861 mtx[0] = mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2;
1862 mtx[1] = mtx[2] = 0;
1863 }
1864 else if (flags & (1 << 6)) { // WE_HAVE_AN_X_AND_YSCALE
1865 mtx[0] = ttSHORT(comp) / 16384.0f; comp += 2;
1866 mtx[1] = mtx[2] = 0;
1867 mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2;
1868 }
1869 else if (flags & (1 << 7)) { // WE_HAVE_A_TWO_BY_TWO
1870 mtx[0] = ttSHORT(comp) / 16384.0f; comp += 2;
1871 mtx[1] = ttSHORT(comp) / 16384.0f; comp += 2;
1872 mtx[2] = ttSHORT(comp) / 16384.0f; comp += 2;
1873 mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2;
1874 }
1875
1876 // Find transformation scales.
1877 m = (float)STBTT_sqrt(mtx[0] * mtx[0] + mtx[1] * mtx[1]);
1878 n = (float)STBTT_sqrt(mtx[2] * mtx[2] + mtx[3] * mtx[3]);
1879
1880 // Get indexed glyph.
1881 comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
1882 if (comp_num_verts > 0) {
1883 // Transform vertices.
1884 for (i = 0; i < comp_num_verts; ++i) {
1885 stbtt_vertex* v = &comp_verts[i];
1887 x = v->x; y = v->y;
1888 v->x = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] * y + mtx[4]));
1889 v->y = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5]));
1890 x = v->cx; y = v->cy;
1891 v->cx = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] * y + mtx[4]));
1892 v->cy = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] * y + mtx[5]));
1893 }
1894 // Append vertices.
1895 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices + comp_num_verts) * sizeof(stbtt_vertex), info->userdata);
1896 if (!tmp) {
1897 if (vertices) STBTT_free(vertices, info->userdata);
1898 if (comp_verts) STBTT_free(comp_verts, info->userdata);
1899 return 0;
1900 }
1901 if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices * sizeof(stbtt_vertex));
1902 STBTT_memcpy(tmp + num_vertices, comp_verts, comp_num_verts * sizeof(stbtt_vertex));
1903 if (vertices) STBTT_free(vertices, info->userdata);
1904 vertices = tmp;
1905 STBTT_free(comp_verts, info->userdata);
1906 num_vertices += comp_num_verts;
1907 }
1908 // More components ?
1909 more = flags & (1 << 5);
1910 }
1911 }
1912 else {
1913 // numberOfCounters == 0, do nothing
1914 }
1915
1916 *pvertices = vertices;
1917 return num_vertices;
1918}
1919
1920typedef struct
1921{
1922 int bounds;
1923 int started;
1924 float first_x, first_y;
1925 float x, y;
1926 stbtt_int32 min_x, max_x, min_y, max_y;
1927
1928 stbtt_vertex* pvertices;
1929 int num_vertices;
1930} stbtt__csctx;
1931
1932#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
1933
1934static void stbtt__track_vertex(stbtt__csctx* c, stbtt_int32 x, stbtt_int32 y)
1935{
1936 if (x > c->max_x || !c->started) c->max_x = x;
1937 if (y > c->max_y || !c->started) c->max_y = y;
1938 if (x < c->min_x || !c->started) c->min_x = x;
1939 if (y < c->min_y || !c->started) c->min_y = y;
1940 c->started = 1;
1941}
1942
1943static 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)
1944{
1945 if (c->bounds) {
1946 stbtt__track_vertex(c, x, y);
1947 if (type == STBTT_vcubic) {
1948 stbtt__track_vertex(c, cx, cy);
1949 stbtt__track_vertex(c, cx1, cy1);
1950 }
1951 }
1952 else {
1953 stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
1954 c->pvertices[c->num_vertices].cx1 = (stbtt_int16)cx1;
1955 c->pvertices[c->num_vertices].cy1 = (stbtt_int16)cy1;
1956 }
1957 c->num_vertices++;
1958}
1959
1960static void stbtt__csctx_close_shape(stbtt__csctx* ctx)
1961{
1962 if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
1963 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
1964}
1965
1966static void stbtt__csctx_rmove_to(stbtt__csctx* ctx, float dx, float dy)
1967{
1968 stbtt__csctx_close_shape(ctx);
1969 ctx->first_x = ctx->x = ctx->x + dx;
1970 ctx->first_y = ctx->y = ctx->y + dy;
1971 stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1972}
1973
1974static void stbtt__csctx_rline_to(stbtt__csctx* ctx, float dx, float dy)
1975{
1976 ctx->x += dx;
1977 ctx->y += dy;
1978 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1979}
1980
1981static void stbtt__csctx_rccurve_to(stbtt__csctx* ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
1982{
1983 float cx1 = ctx->x + dx1;
1984 float cy1 = ctx->y + dy1;
1985 float cx2 = cx1 + dx2;
1986 float cy2 = cy1 + dy2;
1987 ctx->x = cx2 + dx3;
1988 ctx->y = cy2 + dy3;
1989 stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
1990}
1991
1992static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
1993{
1994 int count = stbtt__cff_index_count(&idx);
1995 int bias = 107;
1996 if (count >= 33900)
1997 bias = 32768;
1998 else if (count >= 1240)
1999 bias = 1131;
2000 n += bias;
2001 if (n < 0 || n >= count)
2002 return stbtt__new_buf(NULL, 0);
2003 return stbtt__cff_index_get(idx, n);
2004}
2005
2006static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo* info, int glyph_index)
2007{
2008 stbtt__buf fdselect = info->fdselect;
2009 int nranges, start, end, v, fmt, fdselector = -1, i;
2010
2011 stbtt__buf_seek(&fdselect, 0);
2012 fmt = stbtt__buf_get8(&fdselect);
2013 if (fmt == 0) {
2014 // untested
2015 stbtt__buf_skip(&fdselect, glyph_index);
2016 fdselector = stbtt__buf_get8(&fdselect);
2017 }
2018 else if (fmt == 3) {
2019 nranges = stbtt__buf_get16(&fdselect);
2020 start = stbtt__buf_get16(&fdselect);
2021 for (i = 0; i < nranges; i++) {
2022 v = stbtt__buf_get8(&fdselect);
2023 end = stbtt__buf_get16(&fdselect);
2024 if (glyph_index >= start && glyph_index < end) {
2025 fdselector = v;
2026 break;
2027 }
2028 start = end;
2029 }
2030 }
2031 if (fdselector == -1) stbtt__new_buf(NULL, 0);
2032 return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
2033}
2034
2035static int stbtt__run_charstring(const stbtt_fontinfo* info, int glyph_index, stbtt__csctx* c)
2036{
2037 int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
2038 int has_subrs = 0, clear_stack;
2039 float s[48];
2040 stbtt__buf subr_stack[10], subrs = info->subrs, b;
2041 float f;
2042
2043#define STBTT__CSERR(s) (0)
2044
2045 // this currently ignores the initial width value, which isn't needed if we have hmtx
2046 b = stbtt__cff_index_get(info->charstrings, glyph_index);
2047 while (b.cursor < b.size) {
2048 i = 0;
2049 clear_stack = 1;
2050 b0 = stbtt__buf_get8(&b);
2051 switch (b0) {
2052 // @TODO implement hinting
2053 case 0x13: // hintmask
2054 case 0x14: // cntrmask
2055 if (in_header)
2056 maskbits += (sp / 2); // implicit "vstem"
2057 in_header = 0;
2058 stbtt__buf_skip(&b, (maskbits + 7) / 8);
2059 break;
2060
2061 case 0x01: // hstem
2062 case 0x03: // vstem
2063 case 0x12: // hstemhm
2064 case 0x17: // vstemhm
2065 maskbits += (sp / 2);
2066 break;
2067
2068 case 0x15: // rmoveto
2069 in_header = 0;
2070 if (sp < 2) return STBTT__CSERR("rmoveto stack");
2071 stbtt__csctx_rmove_to(c, s[sp - 2], s[sp - 1]);
2072 break;
2073 case 0x04: // vmoveto
2074 in_header = 0;
2075 if (sp < 1) return STBTT__CSERR("vmoveto stack");
2076 stbtt__csctx_rmove_to(c, 0, s[sp - 1]);
2077 break;
2078 case 0x16: // hmoveto
2079 in_header = 0;
2080 if (sp < 1) return STBTT__CSERR("hmoveto stack");
2081 stbtt__csctx_rmove_to(c, s[sp - 1], 0);
2082 break;
2083
2084 case 0x05: // rlineto
2085 if (sp < 2) return STBTT__CSERR("rlineto stack");
2086 for (; i + 1 < sp; i += 2)
2087 stbtt__csctx_rline_to(c, s[i], s[i + 1]);
2088 break;
2089
2090 // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
2091 // starting from a different place.
2092
2093 case 0x07: // vlineto
2094 if (sp < 1) return STBTT__CSERR("vlineto stack");
2095 goto vlineto;
2096 case 0x06: // hlineto
2097 if (sp < 1) return STBTT__CSERR("hlineto stack");
2098 for (;;) {
2099 if (i >= sp) break;
2100 stbtt__csctx_rline_to(c, s[i], 0);
2101 i++;
2102 vlineto:
2103 if (i >= sp) break;
2104 stbtt__csctx_rline_to(c, 0, s[i]);
2105 i++;
2106 }
2107 break;
2108
2109 case 0x1F: // hvcurveto
2110 if (sp < 4) return STBTT__CSERR("hvcurveto stack");
2111 goto hvcurveto;
2112 case 0x1E: // vhcurveto
2113 if (sp < 4) return STBTT__CSERR("vhcurveto stack");
2114 for (;;) {
2115 if (i + 3 >= sp) break;
2116 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);
2117 i += 4;
2118 hvcurveto:
2119 if (i + 3 >= sp) break;
2120 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]);
2121 i += 4;
2122 }
2123 break;
2124
2125 case 0x08: // rrcurveto
2126 if (sp < 6) return STBTT__CSERR("rcurveline stack");
2127 for (; i + 5 < sp; i += 6)
2128 stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i + 5]);
2129 break;
2130
2131 case 0x18: // rcurveline
2132 if (sp < 8) return STBTT__CSERR("rcurveline stack");
2133 for (; i + 5 < sp - 2; i += 6)
2134 stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i + 5]);
2135 if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
2136 stbtt__csctx_rline_to(c, s[i], s[i + 1]);
2137 break;
2138
2139 case 0x19: // rlinecurve
2140 if (sp < 8) return STBTT__CSERR("rlinecurve stack");
2141 for (; i + 1 < sp - 6; i += 2)
2142 stbtt__csctx_rline_to(c, s[i], s[i + 1]);
2143 if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
2144 stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i + 5]);
2145 break;
2146
2147 case 0x1A: // vvcurveto
2148 case 0x1B: // hhcurveto
2149 if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
2150 f = 0.0;
2151 if (sp & 1) { f = s[i]; i++; }
2152 for (; i + 3 < sp; i += 4) {
2153 if (b0 == 0x1B)
2154 stbtt__csctx_rccurve_to(c, s[i], f, s[i + 1], s[i + 2], s[i + 3], 0.0);
2155 else
2156 stbtt__csctx_rccurve_to(c, f, s[i], s[i + 1], s[i + 2], 0.0, s[i + 3]);
2157 f = 0.0;
2158 }
2159 break;
2160
2161 case 0x0A: // callsubr
2162 if (!has_subrs) {
2163 if (info->fdselect.size)
2164 subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
2165 has_subrs = 1;
2166 }
2167 // FALLTHROUGH
2168 case 0x1D: // callgsubr
2169 if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
2170 v = (int)s[--sp];
2171 if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
2172 subr_stack[subr_stack_height++] = b;
2173 b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
2174 if (b.size == 0) return STBTT__CSERR("subr not found");
2175 b.cursor = 0;
2176 clear_stack = 0;
2177 break;
2178
2179 case 0x0B: // return
2180 if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
2181 b = subr_stack[--subr_stack_height];
2182 clear_stack = 0;
2183 break;
2184
2185 case 0x0E: // endchar
2186 stbtt__csctx_close_shape(c);
2187 return 1;
2188
2189 case 0x0C: { // two-byte escape
2190 float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
2191 float dx, dy;
2192 int b1 = stbtt__buf_get8(&b);
2193 switch (b1) {
2194 // @TODO These "flex" implementations ignore the flex-depth and resolution,
2195 // and always draw beziers.
2196 case 0x22: // hflex
2197 if (sp < 7) return STBTT__CSERR("hflex stack");
2198 dx1 = s[0];
2199 dx2 = s[1];
2200 dy2 = s[2];
2201 dx3 = s[3];
2202 dx4 = s[4];
2203 dx5 = s[5];
2204 dx6 = s[6];
2205 stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
2206 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
2207 break;
2208
2209 case 0x23: // flex
2210 if (sp < 13) return STBTT__CSERR("flex stack");
2211 dx1 = s[0];
2212 dy1 = s[1];
2213 dx2 = s[2];
2214 dy2 = s[3];
2215 dx3 = s[4];
2216 dy3 = s[5];
2217 dx4 = s[6];
2218 dy4 = s[7];
2219 dx5 = s[8];
2220 dy5 = s[9];
2221 dx6 = s[10];
2222 dy6 = s[11];
2223 //fd is s[12]
2224 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2225 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2226 break;
2227
2228 case 0x24: // hflex1
2229 if (sp < 9) return STBTT__CSERR("hflex1 stack");
2230 dx1 = s[0];
2231 dy1 = s[1];
2232 dx2 = s[2];
2233 dy2 = s[3];
2234 dx3 = s[4];
2235 dx4 = s[5];
2236 dx5 = s[6];
2237 dy5 = s[7];
2238 dx6 = s[8];
2239 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
2240 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1 + dy2 + dy5));
2241 break;
2242
2243 case 0x25: // flex1
2244 if (sp < 11) return STBTT__CSERR("flex1 stack");
2245 dx1 = s[0];
2246 dy1 = s[1];
2247 dx2 = s[2];
2248 dy2 = s[3];
2249 dx3 = s[4];
2250 dy3 = s[5];
2251 dx4 = s[6];
2252 dy4 = s[7];
2253 dx5 = s[8];
2254 dy5 = s[9];
2255 dx6 = dy6 = s[10];
2256 dx = dx1 + dx2 + dx3 + dx4 + dx5;
2257 dy = dy1 + dy2 + dy3 + dy4 + dy5;
2258 if (STBTT_fabs(dx) > STBTT_fabs(dy))
2259 dy6 = -dy;
2260 else
2261 dx6 = -dx;
2262 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2263 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2264 break;
2265
2266 default:
2267 return STBTT__CSERR("unimplemented");
2268 }
2269 } break;
2270
2271 default:
2272 if (b0 != 255 && b0 != 28 && b0 < 32)
2273 return STBTT__CSERR("reserved operator");
2274
2275 // push immediate
2276 if (b0 == 255) {
2277 f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
2278 }
2279 else {
2280 stbtt__buf_skip(&b, -1);
2281 f = (float)(stbtt_int16)stbtt__cff_int(&b);
2282 }
2283 if (sp >= 48) return STBTT__CSERR("push stack overflow");
2284 s[sp++] = f;
2285 clear_stack = 0;
2286 break;
2287 }
2288 if (clear_stack) sp = 0;
2289 }
2290 return STBTT__CSERR("no endchar");
2291
2292#undef STBTT__CSERR
2293}
2294
2295static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo* info, int glyph_index, stbtt_vertex** pvertices)
2296{
2297 // runs the charstring twice, once to count and once to output (to avoid realloc)
2298 stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
2299 stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
2300 if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
2301 *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices * sizeof(stbtt_vertex), info->userdata);
2302 output_ctx.pvertices = *pvertices;
2303 if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
2304 STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
2305 return output_ctx.num_vertices;
2306 }
2307 }
2308 *pvertices = NULL;
2309 return 0;
2310}
2311
2312static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo* info, int glyph_index, int* x0, int* y0, int* x1, int* y1)
2313{
2314 stbtt__csctx c = STBTT__CSCTX_INIT(1);
2315 int r = stbtt__run_charstring(info, glyph_index, &c);
2316 if (x0) *x0 = r ? c.min_x : 0;
2317 if (y0) *y0 = r ? c.min_y : 0;
2318 if (x1) *x1 = r ? c.max_x : 0;
2319 if (y1) *y1 = r ? c.max_y : 0;
2320 return r ? c.num_vertices : 0;
2321}
2322
2323STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo* info, int glyph_index, stbtt_vertex** pvertices)
2324{
2325 if (!info->cff.size)
2326 return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
2327 else
2328 return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
2329}
2330
2331STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo* info, int glyph_index, int* advanceWidth, int* leftSideBearing)
2332{
2333 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data + info->hhea + 34);
2334 if (glyph_index < numOfLongHorMetrics) {
2335 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * glyph_index);
2336 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4 * glyph_index + 2);
2337 }
2338 else {
2339 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * (numOfLongHorMetrics - 1));
2340 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4 * numOfLongHorMetrics + 2 * (glyph_index - numOfLongHorMetrics));
2341 }
2342}
2343
2345{
2346 stbtt_uint8* data = info->data + info->kern;
2347
2348 // we only look at the first table. it must be 'horizontal' and format 0.
2349 if (!info->kern)
2350 return 0;
2351 if (ttUSHORT(data + 2) < 1) // number of tables, need at least 1
2352 return 0;
2353 if (ttUSHORT(data + 8) != 1) // horizontal flag must be set in format
2354 return 0;
2355
2356 return ttUSHORT(data + 10);
2357}
2358
2359STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo* info, stbtt_kerningentry* table, int table_length)
2360{
2361 stbtt_uint8* data = info->data + info->kern;
2362 int k, length;
2363
2364 // we only look at the first table. it must be 'horizontal' and format 0.
2365 if (!info->kern)
2366 return 0;
2367 if (ttUSHORT(data + 2) < 1) // number of tables, need at least 1
2368 return 0;
2369 if (ttUSHORT(data + 8) != 1) // horizontal flag must be set in format
2370 return 0;
2371
2372 length = ttUSHORT(data + 10);
2373 if (table_length < length)
2374 length = table_length;
2375
2376 for (k = 0; k < length; k++)
2377 {
2378 table[k].glyph1 = ttUSHORT(data + 18 + (k * 6));
2379 table[k].glyph2 = ttUSHORT(data + 20 + (k * 6));
2380 table[k].advance = ttSHORT(data + 22 + (k * 6));
2381 }
2382
2383 return length;
2384}
2385
2386static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo* info, int glyph1, int glyph2)
2387{
2388 stbtt_uint8* data = info->data + info->kern;
2389 stbtt_uint32 needle, straw;
2390 int l, r, m;
2391
2392 // we only look at the first table. it must be 'horizontal' and format 0.
2393 if (!info->kern)
2394 return 0;
2395 if (ttUSHORT(data + 2) < 1) // number of tables, need at least 1
2396 return 0;
2397 if (ttUSHORT(data + 8) != 1) // horizontal flag must be set in format
2398 return 0;
2399
2400 l = 0;
2401 r = ttUSHORT(data + 10) - 1;
2402 needle = glyph1 << 16 | glyph2;
2403 while (l <= r) {
2404 m = (l + r) >> 1;
2405 straw = ttULONG(data + 18 + (m * 6)); // note: unaligned read
2406 if (needle < straw)
2407 r = m - 1;
2408 else if (needle > straw)
2409 l = m + 1;
2410 else
2411 return ttSHORT(data + 22 + (m * 6));
2412 }
2413 return 0;
2414}
2415
2416static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8* coverageTable, int glyph)
2417{
2418 stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2419 switch (coverageFormat) {
2420 case 1: {
2421 stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2422
2423 // Binary search.
2424 stbtt_int32 l = 0, r = glyphCount - 1, m;
2425 int straw, needle = glyph;
2426 while (l <= r) {
2427 stbtt_uint8* glyphArray = coverageTable + 4;
2428 stbtt_uint16 glyphID;
2429 m = (l + r) >> 1;
2430 glyphID = ttUSHORT(glyphArray + 2 * m);
2431 straw = glyphID;
2432 if (needle < straw)
2433 r = m - 1;
2434 else if (needle > straw)
2435 l = m + 1;
2436 else {
2437 return m;
2438 }
2439 }
2440 break;
2441 }
2442
2443 case 2: {
2444 stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2445 stbtt_uint8* rangeArray = coverageTable + 4;
2446
2447 // Binary search.
2448 stbtt_int32 l = 0, r = rangeCount - 1, m;
2449 int strawStart, strawEnd, needle = glyph;
2450 while (l <= r) {
2451 stbtt_uint8* rangeRecord;
2452 m = (l + r) >> 1;
2453 rangeRecord = rangeArray + 6 * m;
2454 strawStart = ttUSHORT(rangeRecord);
2455 strawEnd = ttUSHORT(rangeRecord + 2);
2456 if (needle < strawStart)
2457 r = m - 1;
2458 else if (needle > strawEnd)
2459 l = m + 1;
2460 else {
2461 stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2462 return startCoverageIndex + glyph - strawStart;
2463 }
2464 }
2465 break;
2466 }
2467
2468 default: return -1; // unsupported
2469 }
2470
2471 return -1;
2472}
2473
2474static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8* classDefTable, int glyph)
2475{
2476 stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2477 switch (classDefFormat)
2478 {
2479 case 1: {
2480 stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2481 stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2482 stbtt_uint8* classDef1ValueArray = classDefTable + 6;
2483
2484 if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2485 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2486 break;
2487 }
2488
2489 case 2: {
2490 stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2491 stbtt_uint8* classRangeRecords = classDefTable + 4;
2492
2493 // Binary search.
2494 stbtt_int32 l = 0, r = classRangeCount - 1, m;
2495 int strawStart, strawEnd, needle = glyph;
2496 while (l <= r) {
2497 stbtt_uint8* classRangeRecord;
2498 m = (l + r) >> 1;
2499 classRangeRecord = classRangeRecords + 6 * m;
2500 strawStart = ttUSHORT(classRangeRecord);
2501 strawEnd = ttUSHORT(classRangeRecord + 2);
2502 if (needle < strawStart)
2503 r = m - 1;
2504 else if (needle > strawEnd)
2505 l = m + 1;
2506 else
2507 return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2508 }
2509 break;
2510 }
2511
2512 default:
2513 return -1; // Unsupported definition type, return an error.
2514 }
2515
2516 // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
2517 return 0;
2518}
2519
2520// Define to STBTT_assert(x) if you want to break on unimplemented formats.
2521#define STBTT_GPOS_TODO_assert(x)
2522
2523static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo* info, int glyph1, int glyph2)
2524{
2525 stbtt_uint16 lookupListOffset;
2526 stbtt_uint8* lookupList;
2527 stbtt_uint16 lookupCount;
2528 stbtt_uint8* data;
2529 stbtt_int32 i, sti;
2530
2531 if (!info->gpos) return 0;
2532
2533 data = info->data + info->gpos;
2534
2535 if (ttUSHORT(data + 0) != 1) return 0; // Major version 1
2536 if (ttUSHORT(data + 2) != 0) return 0; // Minor version 0
2537
2538 lookupListOffset = ttUSHORT(data + 8);
2539 lookupList = data + lookupListOffset;
2540 lookupCount = ttUSHORT(lookupList);
2541
2542 for (i = 0; i < lookupCount; ++i) {
2543 stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2544 stbtt_uint8* lookupTable = lookupList + lookupOffset;
2545
2546 stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2547 stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2548 stbtt_uint8* subTableOffsets = lookupTable + 6;
2549 if (lookupType != 2) // Pair Adjustment Positioning Subtable
2550 continue;
2551
2552 for (sti = 0; sti < subTableCount; sti++) {
2553 stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2554 stbtt_uint8* table = lookupTable + subtableOffset;
2555 stbtt_uint16 posFormat = ttUSHORT(table);
2556 stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2557 stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2558 if (coverageIndex == -1) continue;
2559
2560 switch (posFormat) {
2561 case 1: {
2562 stbtt_int32 l, r, m;
2563 int straw, needle;
2564 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2565 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2566 if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
2567 stbtt_int32 valueRecordPairSizeInBytes = 2;
2568 stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2569 stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2570 stbtt_uint8* pairValueTable = table + pairPosOffset;
2571 stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2572 stbtt_uint8* pairValueArray = pairValueTable + 2;
2573
2574 if (coverageIndex >= pairSetCount) return 0;
2575
2576 needle = glyph2;
2577 r = pairValueCount - 1;
2578 l = 0;
2579
2580 // Binary search.
2581 while (l <= r) {
2582 stbtt_uint16 secondGlyph;
2583 stbtt_uint8* pairValue;
2584 m = (l + r) >> 1;
2585 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2586 secondGlyph = ttUSHORT(pairValue);
2587 straw = secondGlyph;
2588 if (needle < straw)
2589 r = m - 1;
2590 else if (needle > straw)
2591 l = m + 1;
2592 else {
2593 stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2594 return xAdvance;
2595 }
2596 }
2597 }
2598 else
2599 return 0;
2600 break;
2601 }
2602
2603 case 2: {
2604 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2605 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2606 if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
2607 stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2608 stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2609 int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2610 int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2611
2612 stbtt_uint16 class1Count = ttUSHORT(table + 12);
2613 stbtt_uint16 class2Count = ttUSHORT(table + 14);
2614 stbtt_uint8* class1Records, * class2Records;
2615 stbtt_int16 xAdvance;
2616
2617 if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
2618 if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
2619
2620 class1Records = table + 16;
2621 class2Records = class1Records + 2 * (glyph1class * class2Count);
2622 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2623 return xAdvance;
2624 }
2625 else
2626 return 0;
2627 break;
2628 }
2629
2630 default:
2631 return 0; // Unsupported position format
2632 }
2633 }
2634 }
2635
2636 return 0;
2637}
2638
2639STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo* info, int g1, int g2)
2640{
2641 int xAdvance = 0;
2642
2643 if (info->gpos)
2644 xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
2645 else if (info->kern)
2646 xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
2647
2648 return xAdvance;
2649}
2650
2651STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo* info, int ch1, int ch2)
2652{
2653 if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
2654 return 0;
2655 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info, ch1), stbtt_FindGlyphIndex(info, ch2));
2656}
2657
2658STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo* info, int codepoint, int* advanceWidth, int* leftSideBearing)
2659{
2660 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info, codepoint), advanceWidth, leftSideBearing);
2661}
2662
2663STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo* info, int* ascent, int* descent, int* lineGap)
2664{
2665 if (ascent) *ascent = ttSHORT(info->data + info->hhea + 4);
2666 if (descent) *descent = ttSHORT(info->data + info->hhea + 6);
2667 if (lineGap) *lineGap = ttSHORT(info->data + info->hhea + 8);
2668}
2669
2670STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo* info, int* typoAscent, int* typoDescent, int* typoLineGap)
2671{
2672 int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
2673 if (!tab)
2674 return 0;
2675 if (typoAscent) *typoAscent = ttSHORT(info->data + tab + 68);
2676 if (typoDescent) *typoDescent = ttSHORT(info->data + tab + 70);
2677 if (typoLineGap) *typoLineGap = ttSHORT(info->data + tab + 72);
2678 return 1;
2679}
2680
2681STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo* info, int* x0, int* y0, int* x1, int* y1)
2682{
2683 *x0 = ttSHORT(info->data + info->head + 36);
2684 *y0 = ttSHORT(info->data + info->head + 38);
2685 *x1 = ttSHORT(info->data + info->head + 40);
2686 *y1 = ttSHORT(info->data + info->head + 42);
2687}
2688
2689STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo* info, float height)
2690{
2691 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
2692 return (float)height / fheight;
2693}
2694
2695STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo* info, float pixels)
2696{
2697 int unitsPerEm = ttUSHORT(info->data + info->head + 18);
2698 return pixels / unitsPerEm;
2699}
2700
2702{
2703 STBTT_free(v, info->userdata);
2704}
2705
2706STBTT_DEF stbtt_uint8* stbtt_FindSVGDoc(const stbtt_fontinfo* info, int gl)
2707{
2708 int i;
2709 stbtt_uint8* data = info->data;
2710 stbtt_uint8* svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo*)info);
2711
2712 int numEntries = ttUSHORT(svg_doc_list);
2713 stbtt_uint8* svg_docs = svg_doc_list + 2;
2714
2715 for (i = 0; i < numEntries; i++) {
2716 stbtt_uint8* svg_doc = svg_docs + (12 * i);
2717 if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
2718 return svg_doc;
2719 }
2720 return 0;
2721}
2722
2723STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo* info, int gl, const char** svg)
2724{
2725 stbtt_uint8* data = info->data;
2726 stbtt_uint8* svg_doc;
2727
2728 if (info->svg == 0)
2729 return 0;
2730
2731 svg_doc = stbtt_FindSVGDoc(info, gl);
2732 if (svg_doc != NULL) {
2733 *svg = (char*)data + info->svg + ttULONG(svg_doc + 4);
2734 return ttULONG(svg_doc + 8);
2735 }
2736 else {
2737 return 0;
2738 }
2739}
2740
2741STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo* info, int unicode_codepoint, const char** svg)
2742{
2743 return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
2744}
2745
2747//
2748// antialiasing software rasterizer
2749//
2750
2751STBTT_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)
2752{
2753 int x0 = 0, y0 = 0, x1, y1; // =0 suppresses compiler warning
2754 if (!stbtt_GetGlyphBox(font, glyph, &x0, &y0, &x1, &y1)) {
2755 // e.g. space character
2756 if (ix0) *ix0 = 0;
2757 if (iy0) *iy0 = 0;
2758 if (ix1) *ix1 = 0;
2759 if (iy1) *iy1 = 0;
2760 }
2761 else {
2762 // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
2763 if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x + shift_x);
2764 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
2765 if (ix1) *ix1 = STBTT_iceil(x1 * scale_x + shift_x);
2766 if (iy1) *iy1 = STBTT_iceil(-y0 * scale_y + shift_y);
2767 }
2768}
2769
2770STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo* font, int glyph, float scale_x, float scale_y, int* ix0, int* iy0, int* ix1, int* iy1)
2771{
2772 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y, 0.0f, 0.0f, ix0, iy0, ix1, iy1);
2773}
2774
2775STBTT_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)
2776{
2777 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font, codepoint), scale_x, scale_y, shift_x, shift_y, ix0, iy0, ix1, iy1);
2778}
2779
2780STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo* font, int codepoint, float scale_x, float scale_y, int* ix0, int* iy0, int* ix1, int* iy1)
2781{
2782 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y, 0.0f, 0.0f, ix0, iy0, ix1, iy1);
2783}
2784
2786//
2787// Rasterizer
2788
2789typedef struct stbtt__hheap_chunk
2790{
2791 struct stbtt__hheap_chunk* next;
2792} stbtt__hheap_chunk;
2793
2794typedef struct stbtt__hheap
2795{
2796 struct stbtt__hheap_chunk* head;
2797 void* first_free;
2798 int num_remaining_in_head_chunk;
2799} stbtt__hheap;
2800
2801static void* stbtt__hheap_alloc(stbtt__hheap* hh, size_t size, void* userdata)
2802{
2803 if (hh->first_free) {
2804 void* p = hh->first_free;
2805 hh->first_free = *(void**)p;
2806 return p;
2807 }
2808 else {
2809 if (hh->num_remaining_in_head_chunk == 0) {
2810 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
2811 stbtt__hheap_chunk* c = (stbtt__hheap_chunk*)STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
2812 if (c == NULL)
2813 return NULL;
2814 c->next = hh->head;
2815 hh->head = c;
2816 hh->num_remaining_in_head_chunk = count;
2817 }
2818 --hh->num_remaining_in_head_chunk;
2819 return (char*)(hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
2820 }
2821}
2822
2823static void stbtt__hheap_free(stbtt__hheap* hh, void* p)
2824{
2825 *(void**)p = hh->first_free;
2826 hh->first_free = p;
2827}
2828
2829static void stbtt__hheap_cleanup(stbtt__hheap* hh, void* userdata)
2830{
2831 stbtt__hheap_chunk* c = hh->head;
2832 while (c) {
2833 stbtt__hheap_chunk* n = c->next;
2834 STBTT_free(c, userdata);
2835 c = n;
2836 }
2837}
2838
2839typedef struct stbtt__edge {
2840 float x0, y0, x1, y1;
2841 int invert;
2842} stbtt__edge;
2843
2844
2845typedef struct stbtt__active_edge
2846{
2847 struct stbtt__active_edge* next;
2848#if STBTT_RASTERIZER_VERSION==1
2849 int x, dx;
2850 float ey;
2851 int direction;
2852#elif STBTT_RASTERIZER_VERSION==2
2853 float fx, fdx, fdy;
2854 float direction;
2855 float sy;
2856 float ey;
2857#else
2858#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2859#endif
2860} stbtt__active_edge;
2861
2862#if STBTT_RASTERIZER_VERSION == 1
2863#define STBTT_FIXSHIFT 10
2864#define STBTT_FIX (1 << STBTT_FIXSHIFT)
2865#define STBTT_FIXMASK (STBTT_FIX-1)
2866
2867static stbtt__active_edge* stbtt__new_active(stbtt__hheap* hh, stbtt__edge* e, int off_x, float start_point, void* userdata)
2868{
2869 stbtt__active_edge* z = (stbtt__active_edge*)stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2870 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2871 STBTT_assert(z != NULL);
2872 if (!z) return z;
2873
2874 // round dx down to avoid overshooting
2875 if (dxdy < 0)
2876 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
2877 else
2878 z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
2879
2880 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
2881 z->x -= off_x * STBTT_FIX;
2882
2883 z->ey = e->y1;
2884 z->next = 0;
2885 z->direction = e->invert ? 1 : -1;
2886 return z;
2887}
2888#elif STBTT_RASTERIZER_VERSION == 2
2889static stbtt__active_edge* stbtt__new_active(stbtt__hheap* hh, stbtt__edge* e, int off_x, float start_point, void* userdata)
2890{
2891 stbtt__active_edge* z = (stbtt__active_edge*)stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2892 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2893 STBTT_assert(z != NULL);
2894 //STBTT_assert(e->y0 <= start_point);
2895 if (!z) return z;
2896 z->fdx = dxdy;
2897 z->fdy = dxdy != 0.0f ? (1.0f / dxdy) : 0.0f;
2898 z->fx = e->x0 + dxdy * (start_point - e->y0);
2899 z->fx -= off_x;
2900 z->direction = e->invert ? 1.0f : -1.0f;
2901 z->sy = e->y0;
2902 z->ey = e->y1;
2903 z->next = 0;
2904 return z;
2905}
2906#else
2907#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2908#endif
2909
2910#if STBTT_RASTERIZER_VERSION == 1
2911// note: this routine clips fills that extend off the edges... ideally this
2912// wouldn't happen, but it could happen if the truetype glyph bounding boxes
2913// are wrong, or if the user supplies a too-small bitmap
2914static void stbtt__fill_active_edges(unsigned char* scanline, int len, stbtt__active_edge* e, int max_weight)
2915{
2916 // non-zero winding fill
2917 int x0 = 0, w = 0;
2918
2919 while (e) {
2920 if (w == 0) {
2921 // if we're currently at zero, we need to record the edge start point
2922 x0 = e->x; w += e->direction;
2923 }
2924 else {
2925 int x1 = e->x; w += e->direction;
2926 // if we went to zero, we need to draw
2927 if (w == 0) {
2928 int i = x0 >> STBTT_FIXSHIFT;
2929 int j = x1 >> STBTT_FIXSHIFT;
2930
2931 if (i < len && j >= 0) {
2932 if (i == j) {
2933 // x0,x1 are the same pixel, so compute combined coverage
2934 scanline[i] = scanline[i] + (stbtt_uint8)((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
2935 }
2936 else {
2937 if (i >= 0) // add antialiasing for x0
2938 scanline[i] = scanline[i] + (stbtt_uint8)(((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
2939 else
2940 i = -1; // clip
2941
2942 if (j < len) // add antialiasing for x1
2943 scanline[j] = scanline[j] + (stbtt_uint8)(((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
2944 else
2945 j = len; // clip
2946
2947 for (++i; i < j; ++i) // fill pixels between x0 and x1
2948 scanline[i] = scanline[i] + (stbtt_uint8)max_weight;
2949 }
2950 }
2951 }
2952 }
2953
2954 e = e->next;
2955 }
2956}
2957
2958static void stbtt__rasterize_sorted_edges(stbtt__bitmap* result, stbtt__edge* e, int n, int vsubsample, int off_x, int off_y, void* userdata)
2959{
2960 stbtt__hheap hh = { 0, 0, 0 };
2961 stbtt__active_edge* active = NULL;
2962 int y, j = 0;
2963 int max_weight = (255 / vsubsample); // weight per vertical scanline
2964 int s; // vertical subsample index
2965 unsigned char scanline_data[512], * scanline;
2966
2967 if (result->w > 512)
2968 scanline = (unsigned char*)STBTT_malloc(result->w, userdata);
2969 else
2970 scanline = scanline_data;
2971
2972 y = off_y * vsubsample;
2973 e[n].y0 = (off_y + result->h) * (float)vsubsample + 1;
2974
2975 while (j < result->h) {
2976 STBTT_memset(scanline, 0, result->w);
2977 for (s = 0; s < vsubsample; ++s) {
2978 // find center of pixel for this scanline
2979 float scan_y = y + 0.5f;
2980 stbtt__active_edge** step = &active;
2981
2982 // update all active edges;
2983 // remove all active edges that terminate before the center of this scanline
2984 while (*step) {
2985 stbtt__active_edge* z = *step;
2986 if (z->ey <= scan_y) {
2987 *step = z->next; // delete from list
2988 STBTT_assert(z->direction);
2989 z->direction = 0;
2990 stbtt__hheap_free(&hh, z);
2991 }
2992 else {
2993 z->x += z->dx; // advance to position for current scanline
2994 step = &((*step)->next); // advance through list
2995 }
2996 }
2997
2998 // resort the list if needed
2999 for (;;) {
3000 int changed = 0;
3001 step = &active;
3002 while (*step && (*step)->next) {
3003 if ((*step)->x > (*step)->next->x) {
3004 stbtt__active_edge* t = *step;
3005 stbtt__active_edge* q = t->next;
3006
3007 t->next = q->next;
3008 q->next = t;
3009 *step = q;
3010 changed = 1;
3011 }
3012 step = &(*step)->next;
3013 }
3014 if (!changed) break;
3015 }
3016
3017 // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
3018 while (e->y0 <= scan_y) {
3019 if (e->y1 > scan_y) {
3020 stbtt__active_edge* z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
3021 if (z != NULL) {
3022 // find insertion point
3023 if (active == NULL)
3024 active = z;
3025 else if (z->x < active->x) {
3026 // insert at front
3027 z->next = active;
3028 active = z;
3029 }
3030 else {
3031 // find thing to insert AFTER
3032 stbtt__active_edge* p = active;
3033 while (p->next && p->next->x < z->x)
3034 p = p->next;
3035 // at this point, p->next->x is NOT < z->x
3036 z->next = p->next;
3037 p->next = z;
3038 }
3039 }
3040 }
3041 ++e;
3042 }
3043
3044 // now process all active edges in XOR fashion
3045 if (active)
3046 stbtt__fill_active_edges(scanline, result->w, active, max_weight);
3047
3048 ++y;
3049 }
3050 STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
3051 ++j;
3052 }
3053
3054 stbtt__hheap_cleanup(&hh, userdata);
3055
3056 if (scanline != scanline_data)
3057 STBTT_free(scanline, userdata);
3058}
3059
3060#elif STBTT_RASTERIZER_VERSION == 2
3061
3062// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
3063// (i.e. it has already been clipped to those)
3064static void stbtt__handle_clipped_edge(float* scanline, int x, stbtt__active_edge* e, float x0, float y0, float x1, float y1)
3065{
3066 if (y0 == y1) return;
3067 STBTT_assert(y0 < y1);
3068 STBTT_assert(e->sy <= e->ey);
3069 if (y0 > e->ey) return;
3070 if (y1 < e->sy) return;
3071 if (y0 < e->sy) {
3072 x0 += (x1 - x0) * (e->sy - y0) / (y1 - y0);
3073 y0 = e->sy;
3074 }
3075 if (y1 > e->ey) {
3076 x1 += (x1 - x0) * (e->ey - y1) / (y1 - y0);
3077 y1 = e->ey;
3078 }
3079
3080 if (x0 == x)
3081 STBTT_assert(x1 <= x + 1);
3082 else if (x0 == x + 1)
3083 STBTT_assert(x1 >= x);
3084 else if (x0 <= x)
3085 STBTT_assert(x1 <= x);
3086 else if (x0 >= x + 1)
3087 STBTT_assert(x1 >= x + 1);
3088 else
3089 STBTT_assert(x1 >= x && x1 <= x + 1);
3090
3091 if (x0 <= x && x1 <= x)
3092 scanline[x] += e->direction * (y1 - y0);
3093 else if (x0 >= x + 1 && x1 >= x + 1)
3094 ;
3095 else {
3096 STBTT_assert(x0 >= x && x0 <= x + 1 && x1 >= x && x1 <= x + 1);
3097 scanline[x] += e->direction * (y1 - y0) * (1 - ((x0 - x) + (x1 - x)) / 2); // coverage = 1 - average x position
3098 }
3099}
3100
3101static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
3102{
3103 STBTT_assert(top_width >= 0);
3104 STBTT_assert(bottom_width >= 0);
3105 return (top_width + bottom_width) / 2.0f * height;
3106}
3107
3108static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
3109{
3110 return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
3111}
3112
3113static float stbtt__sized_triangle_area(float height, float width)
3114{
3115 return height * width / 2;
3116}
3117
3118static void stbtt__fill_active_edges_new(float* scanline, float* scanline_fill, int len, stbtt__active_edge* e, float y_top)
3119{
3120 float y_bottom = y_top + 1;
3121
3122 while (e) {
3123 // brute force every pixel
3124
3125 // compute intersection points with top & bottom
3126 STBTT_assert(e->ey >= y_top);
3127
3128 if (e->fdx == 0) {
3129 float x0 = e->fx;
3130 if (x0 < len) {
3131 if (x0 >= 0) {
3132 stbtt__handle_clipped_edge(scanline, (int)x0, e, x0, y_top, x0, y_bottom);
3133 stbtt__handle_clipped_edge(scanline_fill - 1, (int)x0 + 1, e, x0, y_top, x0, y_bottom);
3134 }
3135 else {
3136 stbtt__handle_clipped_edge(scanline_fill - 1, 0, e, x0, y_top, x0, y_bottom);
3137 }
3138 }
3139 }
3140 else {
3141 float x0 = e->fx;
3142 float dx = e->fdx;
3143 float xb = x0 + dx;
3144 float x_top, x_bottom;
3145 float sy0, sy1;
3146 float dy = e->fdy;
3147 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
3148
3149 // compute endpoints of line segment clipped to this scanline (if the
3150 // line segment starts on this scanline. x0 is the intersection of the
3151 // line with y_top, but that may be off the line segment.
3152 if (e->sy > y_top) {
3153 x_top = x0 + dx * (e->sy - y_top);
3154 sy0 = e->sy;
3155 }
3156 else {
3157 x_top = x0;
3158 sy0 = y_top;
3159 }
3160 if (e->ey < y_bottom) {
3161 x_bottom = x0 + dx * (e->ey - y_top);
3162 sy1 = e->ey;
3163 }
3164 else {
3165 x_bottom = xb;
3166 sy1 = y_bottom;
3167 }
3168
3169 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
3170 // from here on, we don't have to range check x values
3171
3172 if ((int)x_top == (int)x_bottom) {
3173 float height;
3174 // simple case, only spans one pixel
3175 int x = (int)x_top;
3176 height = (sy1 - sy0) * e->direction;
3177 STBTT_assert(x >= 0 && x < len);
3178 scanline[x] += stbtt__position_trapezoid_area(height, x_top, x + 1.0f, x_bottom, x + 1.0f);
3179 scanline_fill[x] += height; // everything right of this pixel is filled
3180 }
3181 else {
3182 int x, x1, x2;
3183 float y_crossing, y_final, step, sign, area;
3184 // covers 2+ pixels
3185 if (x_top > x_bottom) {
3186 // flip scanline vertically; signed area is the same
3187 float t;
3188 sy0 = y_bottom - (sy0 - y_top);
3189 sy1 = y_bottom - (sy1 - y_top);
3190 t = sy0, sy0 = sy1, sy1 = t;
3191 t = x_bottom, x_bottom = x_top, x_top = t;
3192 dx = -dx;
3193 dy = -dy;
3194 t = x0, x0 = xb, xb = t;
3195 }
3196 STBTT_assert(dy >= 0);
3197 STBTT_assert(dx >= 0);
3198
3199 x1 = (int)x_top;
3200 x2 = (int)x_bottom;
3201 // compute intersection with y axis at x1+1
3202 y_crossing = y_top + dy * (x1 + 1 - x0);
3203
3204 // compute intersection with y axis at x2
3205 y_final = y_top + dy * (x2 - x0);
3206
3207 // x1 x_top x2 x_bottom
3208 // y_top +------|-----+------------+------------+--------|---+------------+
3209 // | | | | | |
3210 // | | | | | |
3211 // sy0 | Txxxxx|............|............|............|............|
3212 // y_crossing | *xxxxx.......|............|............|............|
3213 // | | xxxxx..|............|............|............|
3214 // | | /- xx*xxxx........|............|............|
3215 // | | dy < | xxxxxx..|............|............|
3216 // y_final | | \- | xx*xxx.........|............|
3217 // sy1 | | | | xxxxxB...|............|
3218 // | | | | | |
3219 // | | | | | |
3220 // y_bottom +------------+------------+------------+------------+------------+
3221 //
3222 // goal is to measure the area covered by '.' in each pixel
3223
3224 // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
3225 // @TODO: maybe test against sy1 rather than y_bottom?
3226 if (y_crossing > y_bottom)
3227 y_crossing = y_bottom;
3228
3229 sign = e->direction;
3230
3231 // area of the rectangle covered from sy0..y_crossing
3232 area = sign * (y_crossing - sy0);
3233
3234 // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
3235 scanline[x1] += stbtt__sized_triangle_area(area, x1 + 1 - x_top);
3236
3237 // check if final y_crossing is blown up; no test case for this
3238 if (y_final > y_bottom) {
3239 y_final = y_bottom;
3240 dy = (y_final - y_crossing) / (x2 - (x1 + 1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
3241 }
3242
3243 // in second pixel, area covered by line segment found in first pixel
3244 // is always a rectangle 1 wide * the height of that line segment; this
3245 // is exactly what the variable 'area' stores. it also gets a contribution
3246 // from the line segment within it. the THIRD pixel will get the first
3247 // pixel's rectangle contribution, the second pixel's rectangle contribution,
3248 // and its own contribution. the 'own contribution' is the same in every pixel except
3249 // the leftmost and rightmost, a trapezoid that slides down in each pixel.
3250 // the second pixel's contribution to the third pixel will be the
3251 // rectangle 1 wide times the height change in the second pixel, which is dy.
3252
3253 step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
3254 // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
3255 // so the area advances by 'step' every time
3256
3257 for (x = x1 + 1; x < x2; ++x) {
3258 scanline[x] += area + step / 2; // area of trapezoid is 1*step/2
3259 area += step;
3260 }
3261 STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
3262 STBTT_assert(sy1 > y_final - 0.01f);
3263
3264 // area covered in the last pixel is the rectangle from all the pixels to the left,
3265 // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
3266 scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1 - y_final, (float)x2, x2 + 1.0f, x_bottom, x2 + 1.0f);
3267
3268 // the rest of the line is filled based on the total height of the line segment in this pixel
3269 scanline_fill[x2] += sign * (sy1 - sy0);
3270 }
3271 }
3272 else {
3273 // if edge goes outside of box we're drawing, we require
3274 // clipping logic. since this does not match the intended use
3275 // of this library, we use a different, very slow brute
3276 // force implementation
3277 // note though that this does happen some of the time because
3278 // x_top and x_bottom can be extrapolated at the top & bottom of
3279 // the shape and actually lie outside the bounding box
3280 int x;
3281 for (x = 0; x < len; ++x) {
3282 // cases:
3283 //
3284 // there can be up to two intersections with the pixel. any intersection
3285 // with left or right edges can be handled by splitting into two (or three)
3286 // regions. intersections with top & bottom do not necessitate case-wise logic.
3287 //
3288 // the old way of doing this found the intersections with the left & right edges,
3289 // then used some simple logic to produce up to three segments in sorted order
3290 // from top-to-bottom. however, this had a problem: if an x edge was epsilon
3291 // across the x border, then the corresponding y position might not be distinct
3292 // from the other y segment, and it might ignored as an empty segment. to avoid
3293 // that, we need to explicitly produce segments based on x positions.
3294
3295 // rename variables to clearly-defined pairs
3296 float y0 = y_top;
3297 float x1 = (float)(x);
3298 float x2 = (float)(x + 1);
3299 float x3 = xb;
3300 float y3 = y_bottom;
3301
3302 // x = e->x + e->dx * (y-y_top)
3303 // (y-y_top) = (x - e->x) / e->dx
3304 // y = (x - e->x) / e->dx + y_top
3305 float y1 = (x - x0) / dx + y_top;
3306 float y2 = (x + 1 - x0) / dx + y_top;
3307
3308 if (x0 < x1 && x3 > x2) { // three segments descending down-right
3309 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1);
3310 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x2, y2);
3311 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3);
3312 }
3313 else if (x3 < x1 && x0 > x2) { // three segments descending down-left
3314 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2);
3315 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x1, y1);
3316 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3);
3317 }
3318 else if (x0 < x1 && x3 > x1) { // two segments across x, down-right
3319 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1);
3320 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3);
3321 }
3322 else if (x3 < x1 && x0 > x1) { // two segments across x, down-left
3323 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1);
3324 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3);
3325 }
3326 else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right
3327 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2);
3328 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3);
3329 }
3330 else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left
3331 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2);
3332 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3);
3333 }
3334 else { // one segment
3335 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x3, y3);
3336 }
3337 }
3338 }
3339 }
3340 e = e->next;
3341 }
3342}
3343
3344// directly AA rasterize edges w/o supersampling
3345static void stbtt__rasterize_sorted_edges(stbtt__bitmap* result, stbtt__edge* e, int n, int vsubsample, int off_x, int off_y, void* userdata)
3346{
3347 stbtt__hheap hh = { 0, 0, 0 };
3348 stbtt__active_edge* active = NULL;
3349 int y, j = 0, i;
3350 float scanline_data[129], * scanline, * scanline2;
3351
3352 STBTT__NOTUSED(vsubsample);
3353
3354 if (result->w > 64)
3355 scanline = (float*)STBTT_malloc((result->w * 2 + 1) * sizeof(float), userdata);
3356 else
3357 scanline = scanline_data;
3358
3359 scanline2 = scanline + result->w;
3360
3361 y = off_y;
3362 e[n].y0 = (float)(off_y + result->h) + 1;
3363
3364 while (j < result->h) {
3365 // find center of pixel for this scanline
3366 float scan_y_top = y + 0.0f;
3367 float scan_y_bottom = y + 1.0f;
3368 stbtt__active_edge** step = &active;
3369
3370 STBTT_memset(scanline, 0, result->w * sizeof(scanline[0]));
3371 STBTT_memset(scanline2, 0, (result->w + 1) * sizeof(scanline[0]));
3372
3373 // update all active edges;
3374 // remove all active edges that terminate before the top of this scanline
3375 while (*step) {
3376 stbtt__active_edge* z = *step;
3377 if (z->ey <= scan_y_top) {
3378 *step = z->next; // delete from list
3379 STBTT_assert(z->direction);
3380 z->direction = 0;
3381 stbtt__hheap_free(&hh, z);
3382 }
3383 else {
3384 step = &((*step)->next); // advance through list
3385 }
3386 }
3387
3388 // insert all edges that start before the bottom of this scanline
3389 while (e->y0 <= scan_y_bottom) {
3390 if (e->y0 != e->y1) {
3391 stbtt__active_edge* z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
3392 if (z != NULL) {
3393 if (j == 0 && off_y != 0) {
3394 if (z->ey < scan_y_top) {
3395 // this can happen due to subpixel positioning and some kind of fp rounding error i think
3396 z->ey = scan_y_top;
3397 }
3398 }
3399 STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
3400 // insert at front
3401 z->next = active;
3402 active = z;
3403 }
3404 }
3405 ++e;
3406 }
3407
3408 // now process all active edges
3409 if (active)
3410 stbtt__fill_active_edges_new(scanline, scanline2 + 1, result->w, active, scan_y_top);
3411
3412 {
3413 float sum = 0;
3414 for (i = 0; i < result->w; ++i) {
3415 float k;
3416 int m;
3417 sum += scanline2[i];
3418 k = scanline[i] + sum;
3419 k = (float)STBTT_fabs(k) * 255 + 0.5f;
3420 m = (int)k;
3421 if (m > 255) m = 255;
3422 result->pixels[j * result->stride + i] = (unsigned char)m;
3423 }
3424 }
3425 // advance all the edges
3426 step = &active;
3427 while (*step) {
3428 stbtt__active_edge* z = *step;
3429 z->fx += z->fdx; // advance to position for current scanline
3430 step = &((*step)->next); // advance through list
3431 }
3432
3433 ++y;
3434 ++j;
3435 }
3436
3437 stbtt__hheap_cleanup(&hh, userdata);
3438
3439 if (scanline != scanline_data)
3440 STBTT_free(scanline, userdata);
3441}
3442#else
3443#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3444#endif
3445
3446#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
3447
3448static void stbtt__sort_edges_ins_sort(stbtt__edge* p, int n)
3449{
3450 int i, j;
3451 for (i = 1; i < n; ++i) {
3452 stbtt__edge t = p[i], * a = &t;
3453 j = i;
3454 while (j > 0) {
3455 stbtt__edge* b = &p[j - 1];
3456 int c = STBTT__COMPARE(a, b);
3457 if (!c) break;
3458 p[j] = p[j - 1];
3459 --j;
3460 }
3461 if (i != j)
3462 p[j] = t;
3463 }
3464}
3465
3466static void stbtt__sort_edges_quicksort(stbtt__edge* p, int n)
3467{
3468 /* threshold for transitioning to insertion sort */
3469 while (n > 12) {
3470 stbtt__edge t;
3471 int c01, c12, c, m, i, j;
3472
3473 /* compute median of three */
3474 m = n >> 1;
3475 c01 = STBTT__COMPARE(&p[0], &p[m]);
3476 c12 = STBTT__COMPARE(&p[m], &p[n - 1]);
3477 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
3478 if (c01 != c12) {
3479 /* otherwise, we'll need to swap something else to middle */
3480 int z;
3481 c = STBTT__COMPARE(&p[0], &p[n - 1]);
3482 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
3483 /* 0<mid && mid>n: 0>n => 0; 0<n => n */
3484 z = (c == c12) ? 0 : n - 1;
3485 t = p[z];
3486 p[z] = p[m];
3487 p[m] = t;
3488 }
3489 /* now p[m] is the median-of-three */
3490 /* swap it to the beginning so it won't move around */
3491 t = p[0];
3492 p[0] = p[m];
3493 p[m] = t;
3494
3495 /* partition loop */
3496 i = 1;
3497 j = n - 1;
3498 for (;;) {
3499 /* handling of equality is crucial here */
3500 /* for sentinels & efficiency with duplicates */
3501 for (;; ++i) {
3502 if (!STBTT__COMPARE(&p[i], &p[0])) break;
3503 }
3504 for (;; --j) {
3505 if (!STBTT__COMPARE(&p[0], &p[j])) break;
3506 }
3507 /* make sure we haven't crossed */
3508 if (i >= j) break;
3509 t = p[i];
3510 p[i] = p[j];
3511 p[j] = t;
3512
3513 ++i;
3514 --j;
3515 }
3516 /* recurse on smaller side, iterate on larger */
3517 if (j < (n - i)) {
3518 stbtt__sort_edges_quicksort(p, j);
3519 p = p + i;
3520 n = n - i;
3521 }
3522 else {
3523 stbtt__sort_edges_quicksort(p + i, n - i);
3524 n = j;
3525 }
3526 }
3527}
3528
3529static void stbtt__sort_edges(stbtt__edge* p, int n)
3530{
3531 stbtt__sort_edges_quicksort(p, n);
3532 stbtt__sort_edges_ins_sort(p, n);
3533}
3534
3535typedef struct
3536{
3537 float x, y;
3538} stbtt__point;
3539
3540static 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)
3541{
3542 float y_scale_inv = invert ? -scale_y : scale_y;
3543 stbtt__edge* e;
3544 int n, i, j, k, m;
3545#if STBTT_RASTERIZER_VERSION == 1
3546 int vsubsample = result->h < 8 ? 15 : 5;
3547#elif STBTT_RASTERIZER_VERSION == 2
3548 int vsubsample = 1;
3549#else
3550#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3551#endif
3552 // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
3553
3554 // now we have to blow out the windings into explicit edge lists
3555 n = 0;
3556 for (i = 0; i < windings; ++i)
3557 n += wcount[i];
3558
3559 e = (stbtt__edge*)STBTT_malloc(sizeof(*e) * (n + 1), userdata); // add an extra one as a sentinel
3560 if (e == 0) return;
3561 n = 0;
3562
3563 m = 0;
3564 for (i = 0; i < windings; ++i) {
3565 stbtt__point* p = pts + m;
3566 m += wcount[i];
3567 j = wcount[i] - 1;
3568 for (k = 0; k < wcount[i]; j = k++) {
3569 int a = k, b = j;
3570 // skip the edge if horizontal
3571 if (p[j].y == p[k].y)
3572 continue;
3573 // add edge from j to k to the list
3574 e[n].invert = 0;
3575 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
3576 e[n].invert = 1;
3577 a = j, b = k;
3578 }
3579 e[n].x0 = p[a].x * scale_x + shift_x;
3580 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
3581 e[n].x1 = p[b].x * scale_x + shift_x;
3582 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
3583 ++n;
3584 }
3585 }
3586
3587 // now sort the edges by their highest point (should snap to integer, and then by x)
3588 //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
3589 stbtt__sort_edges(e, n);
3590
3591 // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
3592 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
3593
3594 STBTT_free(e, userdata);
3595}
3596
3597static void stbtt__add_point(stbtt__point* points, int n, float x, float y)
3598{
3599 if (!points) return; // during first pass, it's unallocated
3600 points[n].x = x;
3601 points[n].y = y;
3602}
3603
3604// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
3605static 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)
3606{
3607 // midpoint
3608 float mx = (x0 + 2 * x1 + x2) / 4;
3609 float my = (y0 + 2 * y1 + y2) / 4;
3610 // versus directly drawn line
3611 float dx = (x0 + x2) / 2 - mx;
3612 float dy = (y0 + y2) / 2 - my;
3613 if (n > 16) // 65536 segments on one curve better be enough!
3614 return 1;
3615 if (dx * dx + dy * dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
3616 stbtt__tesselate_curve(points, num_points, x0, y0, (x0 + x1) / 2.0f, (y0 + y1) / 2.0f, mx, my, objspace_flatness_squared, n + 1);
3617 stbtt__tesselate_curve(points, num_points, mx, my, (x1 + x2) / 2.0f, (y1 + y2) / 2.0f, x2, y2, objspace_flatness_squared, n + 1);
3618 }
3619 else {
3620 stbtt__add_point(points, *num_points, x2, y2);
3621 *num_points = *num_points + 1;
3622 }
3623 return 1;
3624}
3625
3626static 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)
3627{
3628 // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
3629 float dx0 = x1 - x0;
3630 float dy0 = y1 - y0;
3631 float dx1 = x2 - x1;
3632 float dy1 = y2 - y1;
3633 float dx2 = x3 - x2;
3634 float dy2 = y3 - y2;
3635 float dx = x3 - x0;
3636 float dy = y3 - y0;
3637 float longlen = (float)(STBTT_sqrt(dx0 * dx0 + dy0 * dy0) + STBTT_sqrt(dx1 * dx1 + dy1 * dy1) + STBTT_sqrt(dx2 * dx2 + dy2 * dy2));
3638 float shortlen = (float)STBTT_sqrt(dx * dx + dy * dy);
3639 float flatness_squared = longlen * longlen - shortlen * shortlen;
3640
3641 if (n > 16) // 65536 segments on one curve better be enough!
3642 return;
3643
3644 if (flatness_squared > objspace_flatness_squared) {
3645 float x01 = (x0 + x1) / 2;
3646 float y01 = (y0 + y1) / 2;
3647 float x12 = (x1 + x2) / 2;
3648 float y12 = (y1 + y2) / 2;
3649 float x23 = (x2 + x3) / 2;
3650 float y23 = (y2 + y3) / 2;
3651
3652 float xa = (x01 + x12) / 2;
3653 float ya = (y01 + y12) / 2;
3654 float xb = (x12 + x23) / 2;
3655 float yb = (y12 + y23) / 2;
3656
3657 float mx = (xa + xb) / 2;
3658 float my = (ya + yb) / 2;
3659
3660 stbtt__tesselate_cubic(points, num_points, x0, y0, x01, y01, xa, ya, mx, my, objspace_flatness_squared, n + 1);
3661 stbtt__tesselate_cubic(points, num_points, mx, my, xb, yb, x23, y23, x3, y3, objspace_flatness_squared, n + 1);
3662 }
3663 else {
3664 stbtt__add_point(points, *num_points, x3, y3);
3665 *num_points = *num_points + 1;
3666 }
3667}
3668
3669// returns number of contours
3670static stbtt__point* stbtt_FlattenCurves(stbtt_vertex* vertices, int num_verts, float objspace_flatness, int** contour_lengths, int* num_contours, void* userdata)
3671{
3672 stbtt__point* points = 0;
3673 int num_points = 0;
3674
3675 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
3676 int i, n = 0, start = 0, pass;
3677
3678 // count how many "moves" there are to get the contour count
3679 for (i = 0; i < num_verts; ++i)
3680 if (vertices[i].type == STBTT_vmove)
3681 ++n;
3682
3683 *num_contours = n;
3684 if (n == 0) return 0;
3685
3686 *contour_lengths = (int*)STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
3687
3688 if (*contour_lengths == 0) {
3689 *num_contours = 0;
3690 return 0;
3691 }
3692
3693 // make two passes through the points so we don't need to realloc
3694 for (pass = 0; pass < 2; ++pass) {
3695 float x = 0, y = 0;
3696 if (pass == 1) {
3697 points = (stbtt__point*)STBTT_malloc(num_points * sizeof(points[0]), userdata);
3698 if (points == NULL) goto error;
3699 }
3700 num_points = 0;
3701 n = -1;
3702 for (i = 0; i < num_verts; ++i) {
3703 switch (vertices[i].type) {
3704 case STBTT_vmove:
3705 // start the next contour
3706 if (n >= 0)
3707 (*contour_lengths)[n] = num_points - start;
3708 ++n;
3709 start = num_points;
3710
3711 x = vertices[i].x, y = vertices[i].y;
3712 stbtt__add_point(points, num_points++, x, y);
3713 break;
3714 case STBTT_vline:
3715 x = vertices[i].x, y = vertices[i].y;
3716 stbtt__add_point(points, num_points++, x, y);
3717 break;
3718 case STBTT_vcurve:
3719 stbtt__tesselate_curve(points, &num_points, x, y,
3720 vertices[i].cx, vertices[i].cy,
3721 vertices[i].x, vertices[i].y,
3722 objspace_flatness_squared, 0);
3723 x = vertices[i].x, y = vertices[i].y;
3724 break;
3725 case STBTT_vcubic:
3726 stbtt__tesselate_cubic(points, &num_points, x, y,
3727 vertices[i].cx, vertices[i].cy,
3728 vertices[i].cx1, vertices[i].cy1,
3729 vertices[i].x, vertices[i].y,
3730 objspace_flatness_squared, 0);
3731 x = vertices[i].x, y = vertices[i].y;
3732 break;
3733 }
3734 }
3735 (*contour_lengths)[n] = num_points - start;
3736 }
3737
3738 return points;
3739error:
3740 STBTT_free(points, userdata);
3741 STBTT_free(*contour_lengths, userdata);
3742 *contour_lengths = 0;
3743 *num_contours = 0;
3744 return NULL;
3745}
3746
3747STBTT_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)
3748{
3749 float scale = scale_x > scale_y ? scale_y : scale_x;
3750 int winding_count = 0;
3751 int* winding_lengths = NULL;
3752 stbtt__point* windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
3753 if (windings) {
3754 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
3755 STBTT_free(winding_lengths, userdata);
3756 STBTT_free(windings, userdata);
3757 }
3758}
3759
3760STBTT_DEF void stbtt_FreeBitmap(unsigned char* bitmap, void* userdata)
3761{
3762 STBTT_free(bitmap, userdata);
3763}
3764
3765STBTT_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)
3766{
3767 int ix0, iy0, ix1, iy1;
3768 stbtt__bitmap gbm;
3769 stbtt_vertex* vertices;
3770 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3771
3772 if (scale_x == 0) scale_x = scale_y;
3773 if (scale_y == 0) {
3774 if (scale_x == 0) {
3775 STBTT_free(vertices, info->userdata);
3776 return NULL;
3777 }
3778 scale_y = scale_x;
3779 }
3780
3781 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0, &iy0, &ix1, &iy1);
3782
3783 // now we get the size
3784 gbm.w = (ix1 - ix0);
3785 gbm.h = (iy1 - iy0);
3786 gbm.pixels = NULL; // in case we error
3787
3788 if (width) *width = gbm.w;
3789 if (height) *height = gbm.h;
3790 if (xoff) *xoff = ix0;
3791 if (yoff) *yoff = iy0;
3792
3793 if (gbm.w && gbm.h) {
3794 gbm.pixels = (unsigned char*)STBTT_malloc(gbm.w * gbm.h, info->userdata);
3795 if (gbm.pixels) {
3796 gbm.stride = gbm.w;
3797
3798 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
3799 }
3800 }
3801 STBTT_free(vertices, info->userdata);
3802 return gbm.pixels;
3803}
3804
3805STBTT_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)
3806{
3807 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
3808}
3809
3810STBTT_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)
3811{
3812 int ix0, iy0;
3813 stbtt_vertex* vertices;
3814 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3815 stbtt__bitmap gbm;
3816
3817 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0, &iy0, 0, 0);
3818 gbm.pixels = output;
3819 gbm.w = out_w;
3820 gbm.h = out_h;
3821 gbm.stride = out_stride;
3822
3823 if (gbm.w && gbm.h)
3824 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
3825
3826 STBTT_free(vertices, info->userdata);
3827}
3828
3829STBTT_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)
3830{
3831 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f, 0.0f, glyph);
3832}
3833
3834STBTT_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)
3835{
3836 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info, codepoint), width, height, xoff, yoff);
3837}
3838
3839STBTT_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)
3840{
3841 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));
3842}
3843
3844STBTT_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)
3845{
3846 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info, codepoint));
3847}
3848
3849STBTT_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)
3850{
3851 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, codepoint, width, height, xoff, yoff);
3852}
3853
3854STBTT_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)
3855{
3856 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f, 0.0f, codepoint);
3857}
3858
3860//
3861// bitmap baking
3862//
3863// This is SUPER-CRAPPY packing to keep source code small
3864
3865static int stbtt_BakeFontBitmap_internal(unsigned char* data, int offset, // font location (use offset=0 for plain .ttf)
3866 float pixel_height, // height of font in pixels
3867 unsigned char* pixels, int pw, int ph, // bitmap to be filled in
3868 int first_char, int num_chars, // characters to bake
3869 stbtt_bakedchar* chardata)
3870{
3871 float scale;
3872 int x, y, bottom_y, i;
3874 f.userdata = NULL;
3875 if (!stbtt_InitFont(&f, data, offset))
3876 return -1;
3877 STBTT_memset(pixels, 0, pw * ph); // background of 0 around pixels
3878 x = y = 1;
3879 bottom_y = 1;
3880
3881 scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
3882
3883 for (i = 0; i < num_chars; ++i) {
3884 int advance, lsb, x0, y0, x1, y1, gw, gh;
3885 int g = stbtt_FindGlyphIndex(&f, first_char + i);
3886 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
3887 stbtt_GetGlyphBitmapBox(&f, g, scale, scale, &x0, &y0, &x1, &y1);
3888 gw = x1 - x0;
3889 gh = y1 - y0;
3890 if (x + gw + 1 >= pw)
3891 y = bottom_y, x = 1; // advance to next row
3892 if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
3893 return -i;
3894 STBTT_assert(x + gw < pw);
3895 STBTT_assert(y + gh < ph);
3896 stbtt_MakeGlyphBitmap(&f, pixels + x + y * pw, gw, gh, pw, scale, scale, g);
3897 chardata[i].x0 = (stbtt_int16)x;
3898 chardata[i].y0 = (stbtt_int16)y;
3899 chardata[i].x1 = (stbtt_int16)(x + gw);
3900 chardata[i].y1 = (stbtt_int16)(y + gh);
3901 chardata[i].xadvance = scale * advance;
3902 chardata[i].xoff = (float)x0;
3903 chardata[i].yoff = (float)y0;
3904 x = x + gw + 1;
3905 if (y + gh + 1 > bottom_y)
3906 bottom_y = y + gh + 1;
3907 }
3908 return bottom_y;
3909}
3910
3911STBTT_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)
3912{
3913 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
3914 float ipw = 1.0f / pw, iph = 1.0f / ph;
3915 const stbtt_bakedchar* b = chardata + char_index;
3916 int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
3917 int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
3918
3919 q->x0 = round_x + d3d_bias;
3920 q->y0 = round_y + d3d_bias;
3921 q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
3922 q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
3923
3924 q->s0 = b->x0 * ipw;
3925 q->t0 = b->y0 * iph;
3926 q->s1 = b->x1 * ipw;
3927 q->t1 = b->y1 * iph;
3928
3929 *xpos += b->xadvance;
3930}
3931
3933//
3934// rectangle packing replacement routines if you don't have stb_rect_pack.h
3935//
3936
3937#ifndef STB_RECT_PACK_VERSION
3938
3939typedef int stbrp_coord;
3940
3942// //
3943// //
3944// COMPILER WARNING ?!?!? //
3945// //
3946// //
3947// if you get a compile warning due to these symbols being defined more than //
3948// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
3949// //
3951
3952typedef struct
3953{
3954 int width, height;
3955 int x, y, bottom_y;
3956} stbrp_context;
3957
3958typedef struct
3959{
3960 unsigned char x;
3961} stbrp_node;
3962
3963struct stbrp_rect
3964{
3965 stbrp_coord x, y;
3966 int id, w, h, was_packed;
3967};
3968
3969static void stbrp_init_target(stbrp_context* con, int pw, int ph, stbrp_node* nodes, int num_nodes)
3970{
3971 con->width = pw;
3972 con->height = ph;
3973 con->x = 0;
3974 con->y = 0;
3975 con->bottom_y = 0;
3976 STBTT__NOTUSED(nodes);
3977 STBTT__NOTUSED(num_nodes);
3978}
3979
3980static void stbrp_pack_rects(stbrp_context* con, stbrp_rect* rects, int num_rects)
3981{
3982 int i;
3983 for (i = 0; i < num_rects; ++i) {
3984 if (con->x + rects[i].w > con->width) {
3985 con->x = 0;
3986 con->y = con->bottom_y;
3987 }
3988 if (con->y + rects[i].h > con->height)
3989 break;
3990 rects[i].x = con->x;
3991 rects[i].y = con->y;
3992 rects[i].was_packed = 1;
3993 con->x += rects[i].w;
3994 if (con->y + rects[i].h > con->bottom_y)
3995 con->bottom_y = con->y + rects[i].h;
3996 }
3997 for (; i < num_rects; ++i)
3998 rects[i].was_packed = 0;
3999}
4000#endif
4001
4003//
4004// bitmap baking
4005//
4006// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
4007// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
4008
4009STBTT_DEF int stbtt_PackBegin(stbtt_pack_context* spc, unsigned char* pixels, int pw, int ph, int stride_in_bytes, int padding, void* alloc_context)
4010{
4011 stbrp_context* context = (stbrp_context*)STBTT_malloc(sizeof(*context), alloc_context);
4012 int num_nodes = pw - padding;
4013 stbrp_node* nodes = (stbrp_node*)STBTT_malloc(sizeof(*nodes) * num_nodes, alloc_context);
4014
4015 if (context == NULL || nodes == NULL) {
4016 if (context != NULL) STBTT_free(context, alloc_context);
4017 if (nodes != NULL) STBTT_free(nodes, alloc_context);
4018 return 0;
4019 }
4020
4021 spc->user_allocator_context = alloc_context;
4022 spc->width = pw;
4023 spc->height = ph;
4024 spc->pixels = pixels;
4025 spc->pack_info = context;
4026 spc->nodes = nodes;
4027 spc->padding = padding;
4028 spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
4029 spc->h_oversample = 1;
4030 spc->v_oversample = 1;
4031 spc->skip_missing = 0;
4032
4033 stbrp_init_target(context, pw - padding, ph - padding, nodes, num_nodes);
4034
4035 if (pixels)
4036 STBTT_memset(pixels, 0, pw * ph); // background of 0 around pixels
4037
4038 return 1;
4039}
4040
4042{
4043 STBTT_free(spc->nodes, spc->user_allocator_context);
4044 STBTT_free(spc->pack_info, spc->user_allocator_context);
4045}
4046
4047STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context* spc, unsigned int h_oversample, unsigned int v_oversample)
4048{
4049 STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
4050 STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
4051 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
4052 spc->h_oversample = h_oversample;
4053 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
4054 spc->v_oversample = v_oversample;
4055}
4056
4058{
4059 spc->skip_missing = skip;
4060}
4061
4062#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
4063
4064static void stbtt__h_prefilter(unsigned char* pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
4065{
4066 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
4067 int safe_w = w - kernel_width;
4068 int j;
4069 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
4070 for (j = 0; j < h; ++j) {
4071 int i;
4072 unsigned int total;
4073 STBTT_memset(buffer, 0, kernel_width);
4074
4075 total = 0;
4076
4077 // make kernel_width a constant in common cases so compiler can optimize out the divide
4078 switch (kernel_width) {
4079 case 2:
4080 for (i = 0; i <= safe_w; ++i) {
4081 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4082 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i];
4083 pixels[i] = (unsigned char)(total / 2);
4084 }
4085 break;
4086 case 3:
4087 for (i = 0; i <= safe_w; ++i) {
4088 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4089 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i];
4090 pixels[i] = (unsigned char)(total / 3);
4091 }
4092 break;
4093 case 4:
4094 for (i = 0; i <= safe_w; ++i) {
4095 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4096 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i];
4097 pixels[i] = (unsigned char)(total / 4);
4098 }
4099 break;
4100 case 5:
4101 for (i = 0; i <= safe_w; ++i) {
4102 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4103 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i];
4104 pixels[i] = (unsigned char)(total / 5);
4105 }
4106 break;
4107 default:
4108 for (i = 0; i <= safe_w; ++i) {
4109 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4110 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i];
4111 pixels[i] = (unsigned char)(total / kernel_width);
4112 }
4113 break;
4114 }
4115
4116 for (; i < w; ++i) {
4117 STBTT_assert(pixels[i] == 0);
4118 total -= buffer[i & STBTT__OVER_MASK];
4119 pixels[i] = (unsigned char)(total / kernel_width);
4120 }
4121
4122 pixels += stride_in_bytes;
4123 }
4124}
4125
4126static void stbtt__v_prefilter(unsigned char* pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
4127{
4128 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
4129 int safe_h = h - kernel_width;
4130 int j;
4131 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
4132 for (j = 0; j < w; ++j) {
4133 int i;
4134 unsigned int total;
4135 STBTT_memset(buffer, 0, kernel_width);
4136
4137 total = 0;
4138
4139 // make kernel_width a constant in common cases so compiler can optimize out the divide
4140 switch (kernel_width) {
4141 case 2:
4142 for (i = 0; i <= safe_h; ++i) {
4143 total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4144 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes];
4145 pixels[i * stride_in_bytes] = (unsigned char)(total / 2);
4146 }
4147 break;
4148 case 3:
4149 for (i = 0; i <= safe_h; ++i) {
4150 total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4151 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes];
4152 pixels[i * stride_in_bytes] = (unsigned char)(total / 3);
4153 }
4154 break;
4155 case 4:
4156 for (i = 0; i <= safe_h; ++i) {
4157 total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4158 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes];
4159 pixels[i * stride_in_bytes] = (unsigned char)(total / 4);
4160 }
4161 break;
4162 case 5:
4163 for (i = 0; i <= safe_h; ++i) {
4164 total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4165 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes];
4166 pixels[i * stride_in_bytes] = (unsigned char)(total / 5);
4167 }
4168 break;
4169 default:
4170 for (i = 0; i <= safe_h; ++i) {
4171 total += pixels[i * stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4172 buffer[(i + kernel_width) & STBTT__OVER_MASK] = pixels[i * stride_in_bytes];
4173 pixels[i * stride_in_bytes] = (unsigned char)(total / kernel_width);
4174 }
4175 break;
4176 }
4177
4178 for (; i < h; ++i) {
4179 STBTT_assert(pixels[i * stride_in_bytes] == 0);
4180 total -= buffer[i & STBTT__OVER_MASK];
4181 pixels[i * stride_in_bytes] = (unsigned char)(total / kernel_width);
4182 }
4183
4184 pixels += 1;
4185 }
4186}
4187
4188static float stbtt__oversample_shift(int oversample)
4189{
4190 if (!oversample)
4191 return 0.0f;
4192
4193 // The prefilter is a box filter of width "oversample",
4194 // which shifts phase by (oversample - 1)/2 pixels in
4195 // oversampled space. We want to shift in the opposite
4196 // direction to counter this.
4197 return (float)-(oversample - 1) / (2.0f * (float)oversample);
4198}
4199
4200// rects array must be big enough to accommodate all characters in the given ranges
4201STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context* spc, const stbtt_fontinfo* info, stbtt_pack_range* ranges, int num_ranges, stbrp_rect* rects)
4202{
4203 int i, j, k;
4204 int missing_glyph_added = 0;
4205
4206 k = 0;
4207 for (i = 0; i < num_ranges; ++i) {
4208 float fh = ranges[i].font_size;
4209 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
4210 ranges[i].h_oversample = (unsigned char)spc->h_oversample;
4211 ranges[i].v_oversample = (unsigned char)spc->v_oversample;
4212 for (j = 0; j < ranges[i].num_chars; ++j) {
4213 int x0, y0, x1, y1;
4214 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4215 int glyph = stbtt_FindGlyphIndex(info, codepoint);
4216 if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
4217 rects[k].w = rects[k].h = 0;
4218 }
4219 else {
4221 scale * spc->h_oversample,
4222 scale * spc->v_oversample,
4223 0, 0,
4224 &x0, &y0, &x1, &y1);
4225 rects[k].w = (stbrp_coord)(x1 - x0 + spc->padding + spc->h_oversample - 1);
4226 rects[k].h = (stbrp_coord)(y1 - y0 + spc->padding + spc->v_oversample - 1);
4227 if (glyph == 0)
4228 missing_glyph_added = 1;
4229 }
4230 ++k;
4231 }
4232 }
4233
4234 return k;
4235}
4236
4237STBTT_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)
4238{
4240 output,
4241 out_w - (prefilter_x - 1),
4242 out_h - (prefilter_y - 1),
4243 out_stride,
4244 scale_x,
4245 scale_y,
4246 shift_x,
4247 shift_y,
4248 glyph);
4249
4250 if (prefilter_x > 1)
4251 stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
4252
4253 if (prefilter_y > 1)
4254 stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
4255
4256 *sub_x = stbtt__oversample_shift(prefilter_x);
4257 *sub_y = stbtt__oversample_shift(prefilter_y);
4258}
4259
4260// rects array must be big enough to accommodate all characters in the given ranges
4262{
4263 int i, j, k, missing_glyph = -1, return_value = 1;
4264
4265 // save current values
4266 int old_h_over = spc->h_oversample;
4267 int old_v_over = spc->v_oversample;
4268
4269 k = 0;
4270 for (i = 0; i < num_ranges; ++i) {
4271 float fh = ranges[i].font_size;
4272 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
4273 float recip_h, recip_v, sub_x, sub_y;
4274 spc->h_oversample = ranges[i].h_oversample;
4275 spc->v_oversample = ranges[i].v_oversample;
4276 recip_h = 1.0f / spc->h_oversample;
4277 recip_v = 1.0f / spc->v_oversample;
4278 sub_x = stbtt__oversample_shift(spc->h_oversample);
4279 sub_y = stbtt__oversample_shift(spc->v_oversample);
4280 for (j = 0; j < ranges[i].num_chars; ++j) {
4281 stbrp_rect* r = &rects[k];
4282 if (r->was_packed && r->w != 0 && r->h != 0) {
4283 stbtt_packedchar* bc = &ranges[i].chardata_for_range[j];
4284 int advance, lsb, x0, y0, x1, y1;
4285 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4286 int glyph = stbtt_FindGlyphIndex(info, codepoint);
4287 stbrp_coord pad = (stbrp_coord)spc->padding;
4288
4289 // pad on left and top
4290 r->x += pad;
4291 r->y += pad;
4292 r->w -= pad;
4293 r->h -= pad;
4294 stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
4295 stbtt_GetGlyphBitmapBox(info, glyph,
4296 scale * spc->h_oversample,
4297 scale * spc->v_oversample,
4298 &x0, &y0, &x1, &y1);
4300 spc->pixels + r->x + r->y * spc->stride_in_bytes,
4301 r->w - spc->h_oversample + 1,
4302 r->h - spc->v_oversample + 1,
4303 spc->stride_in_bytes,
4304 scale * spc->h_oversample,
4305 scale * spc->v_oversample,
4306 0, 0,
4307 glyph);
4308
4309 if (spc->h_oversample > 1)
4310 stbtt__h_prefilter(spc->pixels + r->x + r->y * spc->stride_in_bytes,
4311 r->w, r->h, spc->stride_in_bytes,
4312 spc->h_oversample);
4313
4314 if (spc->v_oversample > 1)
4315 stbtt__v_prefilter(spc->pixels + r->x + r->y * spc->stride_in_bytes,
4316 r->w, r->h, spc->stride_in_bytes,
4317 spc->v_oversample);
4318
4319 bc->x0 = (stbtt_int16)r->x;
4320 bc->y0 = (stbtt_int16)r->y;
4321 bc->x1 = (stbtt_int16)(r->x + r->w);
4322 bc->y1 = (stbtt_int16)(r->y + r->h);
4323 bc->xadvance = scale * advance;
4324 bc->xoff = (float)x0 * recip_h + sub_x;
4325 bc->yoff = (float)y0 * recip_v + sub_y;
4326 bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
4327 bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
4328
4329 if (glyph == 0)
4330 missing_glyph = j;
4331 }
4332 else if (spc->skip_missing) {
4333 return_value = 0;
4334 }
4335 else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
4336 ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
4337 }
4338 else {
4339 return_value = 0; // if any fail, report failure
4340 }
4341
4342 ++k;
4343 }
4344 }
4345
4346 // restore original values
4347 spc->h_oversample = old_h_over;
4348 spc->v_oversample = old_v_over;
4349
4350 return return_value;
4351}
4352
4354{
4355 stbrp_pack_rects((stbrp_context*)spc->pack_info, rects, num_rects);
4356}
4357
4358STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context* spc, const unsigned char* fontdata, int font_index, stbtt_pack_range* ranges, int num_ranges)
4359{
4360 stbtt_fontinfo info;
4361 int i, j, n, return_value = 1;
4362 //stbrp_context *context = (stbrp_context *) spc->pack_info;
4363 stbrp_rect* rects;
4364
4365 // flag all characters as NOT packed
4366 for (i = 0; i < num_ranges; ++i)
4367 for (j = 0; j < ranges[i].num_chars; ++j)
4368 ranges[i].chardata_for_range[j].x0 =
4369 ranges[i].chardata_for_range[j].y0 =
4370 ranges[i].chardata_for_range[j].x1 =
4371 ranges[i].chardata_for_range[j].y1 = 0;
4372
4373 n = 0;
4374 for (i = 0; i < num_ranges; ++i)
4375 n += ranges[i].num_chars;
4376
4377 rects = (stbrp_rect*)STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
4378 if (rects == NULL)
4379 return 0;
4380
4381 info.userdata = spc->user_allocator_context;
4382 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, font_index));
4383
4384 n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
4385
4386 stbtt_PackFontRangesPackRects(spc, rects, n);
4387
4388 return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
4389
4390 STBTT_free(rects, spc->user_allocator_context);
4391 return return_value;
4392}
4393
4394STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context* spc, const unsigned char* fontdata, int font_index, float font_size,
4395 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar* chardata_for_range)
4396{
4397 stbtt_pack_range range;
4398 range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
4400 range.num_chars = num_chars_in_range;
4401 range.chardata_for_range = chardata_for_range;
4402 range.font_size = font_size;
4403 return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
4404}
4405
4406STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char* fontdata, int index, float size, float* ascent, float* descent, float* lineGap)
4407{
4408 int i_ascent, i_descent, i_lineGap;
4409 float scale;
4410 stbtt_fontinfo info;
4411 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
4412 scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
4413 stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
4414 *ascent = (float)i_ascent * scale;
4415 *descent = (float)i_descent * scale;
4416 *lineGap = (float)i_lineGap * scale;
4417}
4418
4419STBTT_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)
4420{
4421 float ipw = 1.0f / pw, iph = 1.0f / ph;
4422 const stbtt_packedchar* b = chardata + char_index;
4423
4424 if (align_to_integer) {
4425 float x = (float)STBTT_ifloor((*xpos + b->xoff) + 0.5f);
4426 float y = (float)STBTT_ifloor((*ypos + b->yoff) + 0.5f);
4427 q->x0 = x;
4428 q->y0 = y;
4429 q->x1 = x + b->xoff2 - b->xoff;
4430 q->y1 = y + b->yoff2 - b->yoff;
4431 }
4432 else {
4433 q->x0 = *xpos + b->xoff;
4434 q->y0 = *ypos + b->yoff;
4435 q->x1 = *xpos + b->xoff2;
4436 q->y1 = *ypos + b->yoff2;
4437 }
4438
4439 q->s0 = b->x0 * ipw;
4440 q->t0 = b->y0 * iph;
4441 q->s1 = b->x1 * ipw;
4442 q->t1 = b->y1 * iph;
4443
4444 *xpos += b->xadvance;
4445}
4446
4448//
4449// sdf computation
4450//
4451
4452#define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
4453#define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
4454
4455static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
4456{
4457 float q0perp = q0[1] * ray[0] - q0[0] * ray[1];
4458 float q1perp = q1[1] * ray[0] - q1[0] * ray[1];
4459 float q2perp = q2[1] * ray[0] - q2[0] * ray[1];
4460 float roperp = orig[1] * ray[0] - orig[0] * ray[1];
4461
4462 float a = q0perp - 2 * q1perp + q2perp;
4463 float b = q1perp - q0perp;
4464 float c = q0perp - roperp;
4465
4466 float s0 = 0., s1 = 0.;
4467 int num_s = 0;
4468
4469 if (a != 0.0) {
4470 float discr = b * b - a * c;
4471 if (discr > 0.0) {
4472 float rcpna = -1 / a;
4473 float d = (float)STBTT_sqrt(discr);
4474 s0 = (b + d) * rcpna;
4475 s1 = (b - d) * rcpna;
4476 if (s0 >= 0.0 && s0 <= 1.0)
4477 num_s = 1;
4478 if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
4479 if (num_s == 0) s0 = s1;
4480 ++num_s;
4481 }
4482 }
4483 }
4484 else {
4485 // 2*b*s + c = 0
4486 // s = -c / (2*b)
4487 s0 = c / (-2 * b);
4488 if (s0 >= 0.0 && s0 <= 1.0)
4489 num_s = 1;
4490 }
4491
4492 if (num_s == 0)
4493 return 0;
4494 else {
4495 float rcp_len2 = 1 / (ray[0] * ray[0] + ray[1] * ray[1]);
4496 float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
4497
4498 float q0d = q0[0] * rayn_x + q0[1] * rayn_y;
4499 float q1d = q1[0] * rayn_x + q1[1] * rayn_y;
4500 float q2d = q2[0] * rayn_x + q2[1] * rayn_y;
4501 float rod = orig[0] * rayn_x + orig[1] * rayn_y;
4502
4503 float q10d = q1d - q0d;
4504 float q20d = q2d - q0d;
4505 float q0rd = q0d - rod;
4506
4507 hits[0][0] = q0rd + s0 * (2.0f - 2.0f * s0) * q10d + s0 * s0 * q20d;
4508 hits[0][1] = a * s0 + b;
4509
4510 if (num_s > 1) {
4511 hits[1][0] = q0rd + s1 * (2.0f - 2.0f * s1) * q10d + s1 * s1 * q20d;
4512 hits[1][1] = a * s1 + b;
4513 return 2;
4514 }
4515 else {
4516 return 1;
4517 }
4518 }
4519}
4520
4521static int equal(float* a, float* b)
4522{
4523 return (a[0] == b[0] && a[1] == b[1]);
4524}
4525
4526static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex* verts)
4527{
4528 int i;
4529 float orig[2], ray[2] = { 1, 0 };
4530 float y_frac;
4531 int winding = 0;
4532
4533 // make sure y never passes through a vertex of the shape
4534 y_frac = (float)STBTT_fmod(y, 1.0f);
4535 if (y_frac < 0.01f)
4536 y += 0.01f;
4537 else if (y_frac > 0.99f)
4538 y -= 0.01f;
4539
4540 orig[0] = x;
4541 orig[1] = y;
4542
4543 // test a ray from (-infinity,y) to (x,y)
4544 for (i = 0; i < nverts; ++i) {
4545 if (verts[i].type == STBTT_vline) {
4546 int x0 = (int)verts[i - 1].x, y0 = (int)verts[i - 1].y;
4547 int x1 = (int)verts[i].x, y1 = (int)verts[i].y;
4548 if (y > STBTT_min(y0, y1) && y < STBTT_max(y0, y1) && x > STBTT_min(x0, x1)) {
4549 float x_inter = (y - y0) / (y1 - y0) * (x1 - x0) + x0;
4550 if (x_inter < x)
4551 winding += (y0 < y1) ? 1 : -1;
4552 }
4553 }
4554 if (verts[i].type == STBTT_vcurve) {
4555 int x0 = (int)verts[i - 1].x, y0 = (int)verts[i - 1].y;
4556 int x1 = (int)verts[i].cx, y1 = (int)verts[i].cy;
4557 int x2 = (int)verts[i].x, y2 = (int)verts[i].y;
4558 int ax = STBTT_min(x0, STBTT_min(x1, x2)), ay = STBTT_min(y0, STBTT_min(y1, y2));
4559 int by = STBTT_max(y0, STBTT_max(y1, y2));
4560 if (y > ay && y < by && x > ax) {
4561 float q0[2], q1[2], q2[2];
4562 float hits[2][2];
4563 q0[0] = (float)x0;
4564 q0[1] = (float)y0;
4565 q1[0] = (float)x1;
4566 q1[1] = (float)y1;
4567 q2[0] = (float)x2;
4568 q2[1] = (float)y2;
4569 if (equal(q0, q1) || equal(q1, q2)) {
4570 x0 = (int)verts[i - 1].x;
4571 y0 = (int)verts[i - 1].y;
4572 x1 = (int)verts[i].x;
4573 y1 = (int)verts[i].y;
4574 if (y > STBTT_min(y0, y1) && y < STBTT_max(y0, y1) && x > STBTT_min(x0, x1)) {
4575 float x_inter = (y - y0) / (y1 - y0) * (x1 - x0) + x0;
4576 if (x_inter < x)
4577 winding += (y0 < y1) ? 1 : -1;
4578 }
4579 }
4580 else {
4581 int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
4582 if (num_hits >= 1)
4583 if (hits[0][0] < 0)
4584 winding += (hits[0][1] < 0 ? -1 : 1);
4585 if (num_hits >= 2)
4586 if (hits[1][0] < 0)
4587 winding += (hits[1][1] < 0 ? -1 : 1);
4588 }
4589 }
4590 }
4591 }
4592 return winding;
4593}
4594
4595static float stbtt__cuberoot(float x)
4596{
4597 if (x < 0)
4598 return -(float)STBTT_pow(-x, 1.0f / 3.0f);
4599 else
4600 return (float)STBTT_pow(x, 1.0f / 3.0f);
4601}
4602
4603// x^3 + a*x^2 + b*x + c = 0
4604static int stbtt__solve_cubic(float a, float b, float c, float* r)
4605{
4606 float s = -a / 3;
4607 float p = b - a * a / 3;
4608 float q = a * (2 * a * a - 9 * b) / 27 + c;
4609 float p3 = p * p * p;
4610 float d = q * q + 4 * p3 / 27;
4611 if (d >= 0) {
4612 float z = (float)STBTT_sqrt(d);
4613 float u = (-q + z) / 2;
4614 float v = (-q - z) / 2;
4615 u = stbtt__cuberoot(u);
4616 v = stbtt__cuberoot(v);
4617 r[0] = s + u + v;
4618 return 1;
4619 }
4620 else {
4621 float u = (float)STBTT_sqrt(-p / 3);
4622 float v = (float)STBTT_acos(-STBTT_sqrt(-27 / p3) * q / 2) / 3; // p3 must be negative, since d is negative
4623 float m = (float)STBTT_cos(v);
4624 float n = (float)STBTT_cos(v - 3.141592 / 2) * 1.732050808f;
4625 r[0] = s + u * 2 * m;
4626 r[1] = s - u * (m + n);
4627 r[2] = s - u * (m - n);
4628
4629 //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?
4630 //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
4631 //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
4632 return 3;
4633 }
4634}
4635
4636STBTT_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)
4637{
4638 float scale_x = scale, scale_y = scale;
4639 int ix0, iy0, ix1, iy1;
4640 int w, h;
4641 unsigned char* data;
4642
4643 if (scale == 0) return NULL;
4644
4645 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f, 0.0f, &ix0, &iy0, &ix1, &iy1);
4646
4647 // if empty, return NULL
4648 if (ix0 == ix1 || iy0 == iy1)
4649 return NULL;
4650
4651 ix0 -= padding;
4652 iy0 -= padding;
4653 ix1 += padding;
4654 iy1 += padding;
4655
4656 w = (ix1 - ix0);
4657 h = (iy1 - iy0);
4658
4659 if (width) *width = w;
4660 if (height) *height = h;
4661 if (xoff) *xoff = ix0;
4662 if (yoff) *yoff = iy0;
4663
4664 // invert for y-downwards bitmaps
4665 scale_y = -scale_y;
4666
4667 {
4668 // distance from singular values (in the same units as the pixel grid)
4669 const float eps = 1. / 1024, eps2 = eps * eps;
4670 int x, y, i, j;
4671 float* precompute;
4672 stbtt_vertex* verts;
4673 int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
4674 data = (unsigned char*)STBTT_malloc(w * h, info->userdata);
4675 precompute = (float*)STBTT_malloc(num_verts * sizeof(float), info->userdata);
4676
4677 for (i = 0, j = num_verts - 1; i < num_verts; j = i++) {
4678 if (verts[i].type == STBTT_vline) {
4679 float x0 = verts[i].x * scale_x, y0 = verts[i].y * scale_y;
4680 float x1 = verts[j].x * scale_x, y1 = verts[j].y * scale_y;
4681 float dist = (float)STBTT_sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
4682 precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist;
4683 }
4684 else if (verts[i].type == STBTT_vcurve) {
4685 float x2 = verts[j].x * scale_x, y2 = verts[j].y * scale_y;
4686 float x1 = verts[i].cx * scale_x, y1 = verts[i].cy * scale_y;
4687 float x0 = verts[i].x * scale_x, y0 = verts[i].y * scale_y;
4688 float bx = x0 - 2 * x1 + x2, by = y0 - 2 * y1 + y2;
4689 float len2 = bx * bx + by * by;
4690 if (len2 >= eps2)
4691 precompute[i] = 1.0f / len2;
4692 else
4693 precompute[i] = 0.0f;
4694 }
4695 else
4696 precompute[i] = 0.0f;
4697 }
4698
4699 for (y = iy0; y < iy1; ++y) {
4700 for (x = ix0; x < ix1; ++x) {
4701 float val;
4702 float min_dist = 999999.0f;
4703 float sx = (float)x + 0.5f;
4704 float sy = (float)y + 0.5f;
4705 float x_gspace = (sx / scale_x);
4706 float y_gspace = (sy / scale_y);
4707
4708 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
4709
4710 for (i = 0; i < num_verts; ++i) {
4711 float x0 = verts[i].x * scale_x, y0 = verts[i].y * scale_y;
4712
4713 if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
4714 float x1 = verts[i - 1].x * scale_x, y1 = verts[i - 1].y * scale_y;
4715
4716 float dist, dist2 = (x0 - sx) * (x0 - sx) + (y0 - sy) * (y0 - sy);
4717 if (dist2 < min_dist * min_dist)
4718 min_dist = (float)STBTT_sqrt(dist2);
4719
4720 // coarse culling against bbox
4721 //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
4722 // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
4723 dist = (float)STBTT_fabs((x1 - x0) * (y0 - sy) - (y1 - y0) * (x0 - sx)) * precompute[i];
4724 STBTT_assert(i != 0);
4725 if (dist < min_dist) {
4726 // check position along line
4727 // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
4728 // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
4729 float dx = x1 - x0, dy = y1 - y0;
4730 float px = x0 - sx, py = y0 - sy;
4731 // 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
4732 // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
4733 float t = -(px * dx + py * dy) / (dx * dx + dy * dy);
4734 if (t >= 0.0f && t <= 1.0f)
4735 min_dist = dist;
4736 }
4737 }
4738 else if (verts[i].type == STBTT_vcurve) {
4739 float x2 = verts[i - 1].x * scale_x, y2 = verts[i - 1].y * scale_y;
4740 float x1 = verts[i].cx * scale_x, y1 = verts[i].cy * scale_y;
4741 float box_x0 = STBTT_min(STBTT_min(x0, x1), x2);
4742 float box_y0 = STBTT_min(STBTT_min(y0, y1), y2);
4743 float box_x1 = STBTT_max(STBTT_max(x0, x1), x2);
4744 float box_y1 = STBTT_max(STBTT_max(y0, y1), y2);
4745 // coarse culling against bbox to avoid computing cubic unnecessarily
4746 if (sx > box_x0 - min_dist && sx < box_x1 + min_dist && sy > box_y0 - min_dist && sy < box_y1 + min_dist) {
4747 int num = 0;
4748 float ax = x1 - x0, ay = y1 - y0;
4749 float bx = x0 - 2 * x1 + x2, by = y0 - 2 * y1 + y2;
4750 float mx = x0 - sx, my = y0 - sy;
4751 float res[3] = { 0.f,0.f,0.f };
4752 float px, py, t, it, dist2;
4753 float a_inv = precompute[i];
4754 if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
4755 float a = 3 * (ax * bx + ay * by);
4756 float b = 2 * (ax * ax + ay * ay) + (mx * bx + my * by);
4757 float c = mx * ax + my * ay;
4758 if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear
4759 if (STBTT_fabs(b) >= eps2) {
4760 res[num++] = -c / b;
4761 }
4762 }
4763 else {
4764 float discriminant = b * b - 4 * a * c;
4765 if (discriminant < 0)
4766 num = 0;
4767 else {
4768 float root = (float)STBTT_sqrt(discriminant);
4769 res[0] = (-b - root) / (2 * a);
4770 res[1] = (-b + root) / (2 * a);
4771 num = 2; // don't bother distinguishing 1-solution case, as code below will still work
4772 }
4773 }
4774 }
4775 else {
4776 float b = 3 * (ax * bx + ay * by) * a_inv; // could precompute this as it doesn't depend on sample point
4777 float c = (2 * (ax * ax + ay * ay) + (mx * bx + my * by)) * a_inv;
4778 float d = (mx * ax + my * ay) * a_inv;
4779 num = stbtt__solve_cubic(b, c, d, res);
4780 }
4781 dist2 = (x0 - sx) * (x0 - sx) + (y0 - sy) * (y0 - sy);
4782 if (dist2 < min_dist * min_dist)
4783 min_dist = (float)STBTT_sqrt(dist2);
4784
4785 if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
4786 t = res[0], it = 1.0f - t;
4787 px = it * it * x0 + 2 * t * it * x1 + t * t * x2;
4788 py = it * it * y0 + 2 * t * it * y1 + t * t * y2;
4789 dist2 = (px - sx) * (px - sx) + (py - sy) * (py - sy);
4790 if (dist2 < min_dist * min_dist)
4791 min_dist = (float)STBTT_sqrt(dist2);
4792 }
4793 if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
4794 t = res[1], it = 1.0f - t;
4795 px = it * it * x0 + 2 * t * it * x1 + t * t * x2;
4796 py = it * it * y0 + 2 * t * it * y1 + t * t * y2;
4797 dist2 = (px - sx) * (px - sx) + (py - sy) * (py - sy);
4798 if (dist2 < min_dist * min_dist)
4799 min_dist = (float)STBTT_sqrt(dist2);
4800 }
4801 if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
4802 t = res[2], it = 1.0f - t;
4803 px = it * it * x0 + 2 * t * it * x1 + t * t * x2;
4804 py = it * it * y0 + 2 * t * it * y1 + t * t * y2;
4805 dist2 = (px - sx) * (px - sx) + (py - sy) * (py - sy);
4806 if (dist2 < min_dist * min_dist)
4807 min_dist = (float)STBTT_sqrt(dist2);
4808 }
4809 }
4810 }
4811 }
4812 if (winding == 0)
4813 min_dist = -min_dist; // if outside the shape, value is negative
4814 val = onedge_value + pixel_dist_scale * min_dist;
4815 if (val < 0)
4816 val = 0;
4817 else if (val > 255)
4818 val = 255;
4819 data[(y - iy0) * w + (x - ix0)] = (unsigned char)val;
4820 }
4821 }
4822 STBTT_free(precompute, info->userdata);
4823 STBTT_free(verts, info->userdata);
4824 }
4825 return data;
4826}
4827
4828STBTT_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)
4829{
4830 return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
4831}
4832
4833STBTT_DEF void stbtt_FreeSDF(unsigned char* bitmap, void* userdata)
4834{
4835 STBTT_free(bitmap, userdata);
4836}
4837
4839//
4840// font name matching -- recommended not to use this
4841//
4842
4843// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
4844static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8* s1, stbtt_int32 len1, stbtt_uint8* s2, stbtt_int32 len2)
4845{
4846 stbtt_int32 i = 0;
4847
4848 // convert utf16 to utf8 and compare the results while converting
4849 while (len2) {
4850 stbtt_uint16 ch = s2[0] * 256 + s2[1];
4851 if (ch < 0x80) {
4852 if (i >= len1) return -1;
4853 if (s1[i++] != ch) return -1;
4854 }
4855 else if (ch < 0x800) {
4856 if (i + 1 >= len1) return -1;
4857 if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
4858 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
4859 }
4860 else if (ch >= 0xd800 && ch < 0xdc00) {
4861 stbtt_uint32 c;
4862 stbtt_uint16 ch2 = s2[2] * 256 + s2[3];
4863 if (i + 3 >= len1) return -1;
4864 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
4865 if (s1[i++] != 0xf0 + (c >> 18)) return -1;
4866 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
4867 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
4868 if (s1[i++] != 0x80 + ((c) & 0x3f)) return -1;
4869 s2 += 2; // plus another 2 below
4870 len2 -= 2;
4871 }
4872 else if (ch >= 0xdc00 && ch < 0xe000) {
4873 return -1;
4874 }
4875 else {
4876 if (i + 2 >= len1) return -1;
4877 if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
4878 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
4879 if (s1[i++] != 0x80 + ((ch) & 0x3f)) return -1;
4880 }
4881 s2 += 2;
4882 len2 -= 2;
4883 }
4884 return i;
4885}
4886
4887static int stbtt_CompareUTF8toUTF16_bigendian_internal(char* s1, int len1, char* s2, int len2)
4888{
4889 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*)s1, len1, (stbtt_uint8*)s2, len2);
4890}
4891
4892// returns results in whatever encoding you request... but note that 2-byte encodings
4893// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
4894STBTT_DEF const char* stbtt_GetFontNameString(const stbtt_fontinfo* font, int* length, int platformID, int encodingID, int languageID, int nameID)
4895{
4896 stbtt_int32 i, count, stringOffset;
4897 stbtt_uint8* fc = font->data;
4898 stbtt_uint32 offset = font->fontstart;
4899 stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
4900 if (!nm) return NULL;
4901
4902 count = ttUSHORT(fc + nm + 2);
4903 stringOffset = nm + ttUSHORT(fc + nm + 4);
4904 for (i = 0; i < count; ++i) {
4905 stbtt_uint32 loc = nm + 6 + 12 * i;
4906 if (platformID == ttUSHORT(fc + loc + 0) && encodingID == ttUSHORT(fc + loc + 2)
4907 && languageID == ttUSHORT(fc + loc + 4) && nameID == ttUSHORT(fc + loc + 6)) {
4908 *length = ttUSHORT(fc + loc + 8);
4909 return (const char*)(fc + stringOffset + ttUSHORT(fc + loc + 10));
4910 }
4911 }
4912 return NULL;
4913}
4914
4915static int stbtt__matchpair(stbtt_uint8* fc, stbtt_uint32 nm, stbtt_uint8* name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
4916{
4917 stbtt_int32 i;
4918 stbtt_int32 count = ttUSHORT(fc + nm + 2);
4919 stbtt_int32 stringOffset = nm + ttUSHORT(fc + nm + 4);
4920
4921 for (i = 0; i < count; ++i) {
4922 stbtt_uint32 loc = nm + 6 + 12 * i;
4923 stbtt_int32 id = ttUSHORT(fc + loc + 6);
4924 if (id == target_id) {
4925 // find the encoding
4926 stbtt_int32 platform = ttUSHORT(fc + loc + 0), encoding = ttUSHORT(fc + loc + 2), language = ttUSHORT(fc + loc + 4);
4927
4928 // is this a Unicode encoding?
4929 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
4930 stbtt_int32 slen = ttUSHORT(fc + loc + 8);
4931 stbtt_int32 off = ttUSHORT(fc + loc + 10);
4932
4933 // check if there's a prefix match
4934 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc + stringOffset + off, slen);
4935 if (matchlen >= 0) {
4936 // check for target_id+1 immediately following, with same encoding & language
4937 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) {
4938 slen = ttUSHORT(fc + loc + 12 + 8);
4939 off = ttUSHORT(fc + loc + 12 + 10);
4940 if (slen == 0) {
4941 if (matchlen == nlen)
4942 return 1;
4943 }
4944 else if (matchlen < nlen && name[matchlen] == ' ') {
4945 ++matchlen;
4946 if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*)(name + matchlen), nlen - matchlen, (char*)(fc + stringOffset + off), slen))
4947 return 1;
4948 }
4949 }
4950 else {
4951 // if nothing immediately following
4952 if (matchlen == nlen)
4953 return 1;
4954 }
4955 }
4956 }
4957
4958 // @TODO handle other encodings
4959 }
4960 }
4961 return 0;
4962}
4963
4964static int stbtt__matches(stbtt_uint8* fc, stbtt_uint32 offset, stbtt_uint8* name, stbtt_int32 flags)
4965{
4966 stbtt_int32 nlen = (stbtt_int32)STBTT_strlen((char*)name);
4967 stbtt_uint32 nm, hd;
4968 if (!stbtt__isfont(fc + offset)) return 0;
4969
4970 // check italics/bold/underline flags in macStyle...
4971 if (flags) {
4972 hd = stbtt__find_table(fc, offset, "head");
4973 if ((ttUSHORT(fc + hd + 44) & 7) != (flags & 7)) return 0;
4974 }
4975
4976 nm = stbtt__find_table(fc, offset, "name");
4977 if (!nm) return 0;
4978
4979 if (flags) {
4980 // if we checked the macStyle flags, then just check the family and ignore the subfamily
4981 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
4982 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
4983 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4984 }
4985 else {
4986 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
4987 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
4988 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4989 }
4990
4991 return 0;
4992}
4993
4994static int stbtt_FindMatchingFont_internal(unsigned char* font_collection, char* name_utf8, stbtt_int32 flags)
4995{
4996 stbtt_int32 i;
4997 for (i = 0;; ++i) {
4998 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
4999 if (off < 0) return off;
5000 if (stbtt__matches((stbtt_uint8*)font_collection, off, (stbtt_uint8*)name_utf8, flags))
5001 return off;
5002 }
5003}
5004
5005#if defined(__GNUC__) || defined(__clang__)
5006#pragma GCC diagnostic push
5007#pragma GCC diagnostic ignored "-Wcast-qual"
5008#endif
5009
5010STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char* data, int offset,
5011 float pixel_height, unsigned char* pixels, int pw, int ph,
5012 int first_char, int num_chars, stbtt_bakedchar* chardata)
5013{
5014 return stbtt_BakeFontBitmap_internal((unsigned char*)data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
5015}
5016
5017STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char* data, int index)
5018{
5019 return stbtt_GetFontOffsetForIndex_internal((unsigned char*)data, index);
5020}
5021
5022STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char* data)
5023{
5024 return stbtt_GetNumberOfFonts_internal((unsigned char*)data);
5025}
5026
5027STBTT_DEF int stbtt_InitFont(stbtt_fontinfo* info, const unsigned char* data, int offset)
5028{
5029 return stbtt_InitFont_internal(info, (unsigned char*)data, offset);
5030}
5031
5032STBTT_DEF int stbtt_FindMatchingFont(const unsigned char* fontdata, const char* name, int flags)
5033{
5034 return stbtt_FindMatchingFont_internal((unsigned char*)fontdata, (char*)name, flags);
5035}
5036
5037STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char* s1, int len1, const char* s2, int len2)
5038{
5039 return stbtt_CompareUTF8toUTF16_bigendian_internal((char*)s1, len1, (char*)s2, len2);
5040}
5041
5042#if defined(__GNUC__) || defined(__clang__)
5043#pragma GCC diagnostic pop
5044#endif
5045
5046#endif // STB_TRUETYPE_IMPLEMENTATION
5047
5048
5049// FULL VERSION HISTORY
5050//
5051// 1.25 (2021-07-11) many fixes
5052// 1.24 (2020-02-05) fix warning
5053// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
5054// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
5055// 1.21 (2019-02-25) fix warning
5056// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
5057// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
5058// 1.18 (2018-01-29) add missing function
5059// 1.17 (2017-07-23) make more arguments const; doc fix
5060// 1.16 (2017-07-12) SDF support
5061// 1.15 (2017-03-03) make more arguments const
5062// 1.14 (2017-01-16) num-fonts-in-TTC function
5063// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
5064// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
5065// 1.11 (2016-04-02) fix unused-variable warning
5066// 1.10 (2016-04-02) allow user-defined fabs() replacement
5067// fix memory leak if fontsize=0.0
5068// fix warning from duplicate typedef
5069// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
5070// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
5071// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
5072// allow PackFontRanges to pack and render in separate phases;
5073// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
5074// fixed an assert() bug in the new rasterizer
5075// replace assert() with STBTT_assert() in new rasterizer
5076// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
5077// also more precise AA rasterizer, except if shapes overlap
5078// remove need for STBTT_sort
5079// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
5080// 1.04 (2015-04-15) typo in example
5081// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
5082// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
5083// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
5084// non-oversampled; STBTT_POINT_SIZE for packed case only
5085// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
5086// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
5087// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
5088// 0.8b (2014-07-07) fix a warning
5089// 0.8 (2014-05-25) fix a few more warnings
5090// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
5091// 0.6c (2012-07-24) improve documentation
5092// 0.6b (2012-07-20) fix a few more warnings
5093// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
5094// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
5095// 0.5 (2011-12-09) bugfixes:
5096// subpixel glyph renderer computed wrong bounding box
5097// first vertex of shape can be off-curve (FreeSans)
5098// 0.4b (2011-12-03) fixed an error in the font baking example
5099// 0.4 (2011-12-01) kerning, subpixel rendering (tor)
5100// bugfixes for:
5101// codepoint-to-glyph conversion using table fmt=12
5102// codepoint-to-glyph conversion using table fmt=4
5103// stbtt_GetBakedQuad with non-square texture (Zer)
5104// updated Hello World! sample to use kerning and subpixel
5105// fixed some warnings
5106// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
5107// userdata, malloc-from-userdata, non-zero fill (stb)
5108// 0.2 (2009-03-11) Fix unsigned/signed char warnings
5109// 0.1 (2009-03-09) First public release
5110//
5111
5112/*
5113------------------------------------------------------------------------------
5114This software is available under 2 licenses -- choose whichever you prefer.
5115------------------------------------------------------------------------------
5116ALTERNATIVE A - MIT License
5117Copyright (c) 2017 Sean Barrett
5118Permission is hereby granted, free of charge, to any person obtaining a copy of
5119this software and associated documentation files (the "Software"), to deal in
5120the Software without restriction, including without limitation the rights to
5121use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
5122of the Software, and to permit persons to whom the Software is furnished to do
5123so, subject to the following conditions:
5124The above copyright notice and this permission notice shall be included in all
5125copies or substantial portions of the Software.
5126THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5127IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5128FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5129AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5130LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5131OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5132SOFTWARE.
5133------------------------------------------------------------------------------
5134ALTERNATIVE B - Public Domain (www.unlicense.org)
5135This is free and unencumbered software released into the public domain.
5136Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
5137software, either in source code form or as a compiled binary, for any purpose,
5138commercial or non-commercial, and by any means.
5139In jurisdictions that recognize copyright laws, the author or authors of this
5140software dedicate any and all copyright interest in the software to the public
5141domain. We make this dedication for the benefit of the public at large and to
5142the detriment of our heirs and successors. We intend this dedication to be an
5143overt act of relinquishment in perpetuity of all present and future rights to
5144this software under copyright law.
5145THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5146IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5147FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5148AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
5149ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
5150WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5151------------------------------------------------------------------------------
5152*/
int putchar(int)
Definition stdio.cpp:249
int atoi(const char *s)
Definition stdio.cpp:107
size_t xpos
Definition video.cpp:33
size_t ypos
Definition video.cpp:34
XE_LIB FILE * fopen(const char *name, const char *mode)
Definition stdio.cpp:42
XE_LIB size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
Definition stdio.cpp:93
#define index(str, chr)
Definition string.h:66
int main(int argc, char *argv[])
Definition main.cpp:351
XETime t
Definition main.cpp:53
#define NULL
Definition actypes.h:561
#define sign(x)
Definition draw.cpp:36
char end[]
XE_LIB double floor(double)
Definition math.cpp:134
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)
STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
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)
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry *table, int table_length)
STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
@ STBTT_MS_LANG_DUTCH
Definition stb_truetype.h:1078
@ STBTT_MS_LANG_JAPANESE
Definition stb_truetype.h:1077
@ STBTT_MS_LANG_SWEDISH
Definition stb_truetype.h:1081
@ STBTT_MS_LANG_FRENCH
Definition stb_truetype.h:1079
@ STBTT_MS_LANG_SPANISH
Definition stb_truetype.h:1080
@ STBTT_MS_LANG_CHINESE
Definition stb_truetype.h:1077
@ STBTT_MS_LANG_ENGLISH
Definition stb_truetype.h:1076
@ STBTT_MS_LANG_RUSSIAN
Definition stb_truetype.h:1079
@ STBTT_MS_LANG_ITALIAN
Definition stb_truetype.h:1076
@ STBTT_MS_LANG_KOREAN
Definition stb_truetype.h:1078
@ STBTT_MS_LANG_GERMAN
Definition stb_truetype.h:1080
@ STBTT_MS_LANG_HEBREW
Definition stb_truetype.h:1081
STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
@ STBTT_MS_EID_UNICODE_FULL
Definition stb_truetype.h:1064
@ STBTT_MS_EID_SYMBOL
Definition stb_truetype.h:1061
@ STBTT_MS_EID_SHIFTJIS
Definition stb_truetype.h:1063
@ STBTT_MS_EID_UNICODE_BMP
Definition stb_truetype.h:1062
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)
STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
STBTT_DEF const char * stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
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)
@ STBTT_MAC_LANG_SWEDISH
Definition stb_truetype.h:1089
@ STBTT_MAC_LANG_KOREAN
Definition stb_truetype.h:1086
@ STBTT_MAC_LANG_ITALIAN
Definition stb_truetype.h:1091
@ STBTT_MAC_LANG_SPANISH
Definition stb_truetype.h:1088
@ STBTT_MAC_LANG_CHINESE_SIMPLIFIED
Definition stb_truetype.h:1090
@ STBTT_MAC_LANG_ENGLISH
Definition stb_truetype.h:1085
@ STBTT_MAC_LANG_JAPANESE
Definition stb_truetype.h:1085
@ STBTT_MAC_LANG_FRENCH
Definition stb_truetype.h:1088
@ STBTT_MAC_LANG_HEBREW
Definition stb_truetype.h:1090
@ STBTT_MAC_LANG_GERMAN
Definition stb_truetype.h:1089
@ STBTT_MAC_LANG_ARABIC
Definition stb_truetype.h:1086
@ STBTT_MAC_LANG_DUTCH
Definition stb_truetype.h:1087
@ STBTT_MAC_LANG_CHINESE_TRAD
Definition stb_truetype.h:1091
@ STBTT_MAC_LANG_RUSSIAN
Definition stb_truetype.h:1087
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)
STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
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)
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)
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)
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
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)
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices)
STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
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)
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)
struct stbrp_rect stbrp_rect
Definition stb_truetype.h:586
STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
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)
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices)
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
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)
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)
@ STBTT_UNICODE_EID_ISO_10646
Definition stb_truetype.h:1055
@ STBTT_UNICODE_EID_UNICODE_2_0_BMP
Definition stb_truetype.h:1056
@ STBTT_UNICODE_EID_UNICODE_2_0_FULL
Definition stb_truetype.h:1057
@ STBTT_UNICODE_EID_UNICODE_1_1
Definition stb_truetype.h:1054
@ STBTT_UNICODE_EID_UNICODE_1_0
Definition stb_truetype.h:1053
STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, float pixel_height, unsigned char *pixels, int pw, int ph, int first_char, int num_chars, stbtt_bakedchar *chardata)
@ STBTT_PLATFORM_ID_UNICODE
Definition stb_truetype.h:1046
@ STBTT_PLATFORM_ID_MICROSOFT
Definition stb_truetype.h:1049
@ STBTT_PLATFORM_ID_ISO
Definition stb_truetype.h:1048
@ STBTT_PLATFORM_ID_MAC
Definition stb_truetype.h:1047
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)
STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels)
STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
STBTT_DEF unsigned char * stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
#define STBTT_DEF
Definition stb_truetype.h:506
STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc)
STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
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)
#define stbtt_vertex_type
Definition stb_truetype.h:835
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)
STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
@ STBTT_MAC_EID_KOREAN
Definition stb_truetype.h:1071
@ STBTT_MAC_EID_ROMAN
Definition stb_truetype.h:1068
@ STBTT_MAC_EID_HEBREW
Definition stb_truetype.h:1069
@ STBTT_MAC_EID_CHINESE_TRAD
Definition stb_truetype.h:1070
@ STBTT_MAC_EID_JAPANESE
Definition stb_truetype.h:1069
@ STBTT_MAC_EID_RUSSIAN
Definition stb_truetype.h:1071
@ STBTT_MAC_EID_GREEK
Definition stb_truetype.h:1070
@ STBTT_MAC_EID_ARABIC
Definition stb_truetype.h:1068
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)
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)
@ STBTT_vmove
Definition stb_truetype.h:826
@ STBTT_vcubic
Definition stb_truetype.h:829
@ STBTT_vcurve
Definition stb_truetype.h:828
@ STBTT_vline
Definition stb_truetype.h:827
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
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)
STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
Definition stb_truetype.h:926
int h
Definition stb_truetype.h:927
int stride
Definition stb_truetype.h:927
unsigned char * pixels
Definition stb_truetype.h:928
int w
Definition stb_truetype.h:927
Definition stb_truetype.h:515
int size
Definition stb_truetype.h:518
unsigned char * data
Definition stb_truetype.h:516
int cursor
Definition stb_truetype.h:517
Definition stb_truetype.h:545
float s1
Definition stb_truetype.h:547
float x1
Definition stb_truetype.h:547
float y0
Definition stb_truetype.h:546
float y1
Definition stb_truetype.h:547
float t0
Definition stb_truetype.h:546
float s0
Definition stb_truetype.h:546
float x0
Definition stb_truetype.h:546
float t1
Definition stb_truetype.h:547
Definition stb_truetype.h:529
float xoff
Definition stb_truetype.h:531
unsigned short x1
Definition stb_truetype.h:530
unsigned short x0
Definition stb_truetype.h:530
float yoff
Definition stb_truetype.h:531
unsigned short y1
Definition stb_truetype.h:530
float xadvance
Definition stb_truetype.h:531
unsigned short y0
Definition stb_truetype.h:530
Definition stb_truetype.h:715
int index_map
Definition stb_truetype.h:723
int fontstart
Definition stb_truetype.h:718
int loca
Definition stb_truetype.h:722
int svg
Definition stb_truetype.h:722
stbtt__buf fdselect
Definition stb_truetype.h:731
int kern
Definition stb_truetype.h:722
int glyf
Definition stb_truetype.h:722
int indexToLocFormat
Definition stb_truetype.h:724
stbtt__buf cff
Definition stb_truetype.h:726
int numGlyphs
Definition stb_truetype.h:720
int hhea
Definition stb_truetype.h:722
stbtt__buf fontdicts
Definition stb_truetype.h:730
void * userdata
Definition stb_truetype.h:716
stbtt__buf charstrings
Definition stb_truetype.h:727
int head
Definition stb_truetype.h:722
int gpos
Definition stb_truetype.h:722
stbtt__buf subrs
Definition stb_truetype.h:729
int hmtx
Definition stb_truetype.h:722
unsigned char * data
Definition stb_truetype.h:717
stbtt__buf gsubrs
Definition stb_truetype.h:728
Definition stb_truetype.h:806
int advance
Definition stb_truetype.h:809
int glyph1
Definition stb_truetype.h:807
int glyph2
Definition stb_truetype.h:808
Definition stb_truetype.h:679
int padding
Definition stb_truetype.h:685
void * nodes
Definition stb_truetype.h:689
void * pack_info
Definition stb_truetype.h:681
int skip_missing
Definition stb_truetype.h:686
void * user_allocator_context
Definition stb_truetype.h:680
unsigned int v_oversample
Definition stb_truetype.h:687
int width
Definition stb_truetype.h:682
unsigned char * pixels
Definition stb_truetype.h:688
int height
Definition stb_truetype.h:683
int stride_in_bytes
Definition stb_truetype.h:684
unsigned int h_oversample
Definition stb_truetype.h:687
Definition stb_truetype.h:621
int num_chars
Definition stb_truetype.h:625
int * array_of_unicode_codepoints
Definition stb_truetype.h:624
float font_size
Definition stb_truetype.h:622
int first_unicode_codepoint_in_range
Definition stb_truetype.h:623
unsigned char v_oversample
Definition stb_truetype.h:627
unsigned char h_oversample
Definition stb_truetype.h:627
stbtt_packedchar * chardata_for_range
Definition stb_truetype.h:626
Definition stb_truetype.h:577
unsigned short x0
Definition stb_truetype.h:578
float xadvance
Definition stb_truetype.h:579
float yoff2
Definition stb_truetype.h:580
float xoff2
Definition stb_truetype.h:580
unsigned short y0
Definition stb_truetype.h:578
float yoff
Definition stb_truetype.h:579
unsigned short y1
Definition stb_truetype.h:578
unsigned short x1
Definition stb_truetype.h:578
float xoff
Definition stb_truetype.h:579
Definition stb_truetype.h:837
stbtt_vertex_type cx
Definition stb_truetype.h:838
stbtt_vertex_type cy
Definition stb_truetype.h:838
stbtt_vertex_type x
Definition stb_truetype.h:838
unsigned char padding
Definition stb_truetype.h:839
stbtt_vertex_type y
Definition stb_truetype.h:838
unsigned char type
Definition stb_truetype.h:839
int x
Definition term.cpp:49
TTY * last
Definition tty.cpp:48
TTY * root
Definition tty.cpp:47