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