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