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

source code of qt3d/src/3rdparty/imgui/imstb_truetype.h