source: opengl-game/IMGUI/stb_truetype.h@ c58ebc3

feature/imgui-sdl points-test
Last change on this file since c58ebc3 was c58ebc3, checked in by Dmitry Portnoy <dmp1488@…>, 6 years ago

Create an IMGUI folder for the imgui library files.

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