1 // stb_truetype.h - v1.05 - public domain
2 // authored from 2009-2014 by Sean Barrett / RAD Game Tools
4 // This library processes TrueType files:
6 // extract glyph metrics
7 // extract glyph shapes
8 // render glyphs to one-channel bitmaps with antialiasing (box filter)
12 // crashproof on bad data
13 // hinting? (no longer patented)
14 // cleartype-style AA?
15 // optimize: use simple memory allocator for intermediates
16 // optimize: build edge-list directly from curves
17 // optimize: rasterize directly from curves?
19 // ADDITIONAL CONTRIBUTORS
21 // Mikko Mononen: compound shape support, more cmap formats
22 // Tor Andersson: kerning, subpixel rendering
24 // Bug/warning reports/fixes:
25 // "Zer" on mollyrocket (with fix)
27 // stoiko (Haemimont Games)
36 // Fabian "ryg" Giesen
48 // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
49 // 1.04 (2015-04-15) typo in example
50 // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
51 // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
52 // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
53 // non-oversampled; STBTT_POINT_SIZE for packed case only
54 // 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
55 // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
56 // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
57 // 0.8b (2014-07-07) fix a warning
58 // 0.8 (2014-05-25) fix a few more warnings
59 // 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
60 // 0.6c (2012-07-24) improve documentation
61 // 0.6b (2012-07-20) fix a few more warnings
62 // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
63 // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
64 // 0.5 (2011-12-09) bugfixes:
65 // subpixel glyph renderer computed wrong bounding box
66 // first vertex of shape can be off-curve (FreeSans)
67 // 0.4b (2011-12-03) fixed an error in the font baking example
68 // 0.4 (2011-12-01) kerning, subpixel rendering (tor)
70 // codepoint-to-glyph conversion using table fmt=12
71 // codepoint-to-glyph conversion using table fmt=4
72 // stbtt_GetBakedQuad with non-square texture (Zer)
73 // updated Hello World! sample to use kerning and subpixel
74 // fixed some warnings
75 // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
76 // userdata, malloc-from-userdata, non-zero fill (stb)
77 // 0.2 (2009-03-11) Fix unsigned/signed char warnings
78 // 0.1 (2009-03-09) First public release
82 // This software is in the public domain. Where that dedication is not
83 // recognized, you are granted a perpetual, irrevokable license to copy
84 // and modify this file as you see fit.
88 // Include this file in whatever places neeed to refer to it. In ONE C/C++
90 // #define STB_TRUETYPE_IMPLEMENTATION
91 // before the #include of this file. This expands out the actual
92 // implementation into that C/C++ file.
94 // To make the implementation private to the file that generates the implementation,
95 // #define STBTT_STATIC
97 // Simple 3D API (don't ship this, but it's fine for tools and quick start)
98 // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
99 // stbtt_GetBakedQuad() -- compute quad to draw for a given char
101 // Improved 3D API (more shippable):
102 // #include "stb_rect_pack.h" -- optional, but you really want it
104 // stbtt_PackSetOversample() -- for improved quality on small fonts
105 // stbtt_PackFontRanges()
107 // stbtt_GetPackedQuad()
109 // "Load" a font file from a memory buffer (you have to keep the buffer loaded)
111 // stbtt_GetFontOffsetForIndex() -- use for TTC font collections
113 // Render a unicode codepoint to a bitmap
114 // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
115 // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
116 // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
118 // Character advance/positioning
119 // stbtt_GetCodepointHMetrics()
120 // stbtt_GetFontVMetrics()
121 // stbtt_GetCodepointKernAdvance()
123 // ADDITIONAL DOCUMENTATION
125 // Immediately after this block comment are a series of sample programs.
127 // After the sample programs is the "header file" section. This section
128 // includes documentation for each API function.
130 // Some important concepts to understand to use this library:
133 // Characters are defined by unicode codepoints, e.g. 65 is
134 // uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
135 // the hiragana for "ma".
138 // A visual character shape (every codepoint is rendered as
142 // A font-specific integer ID representing a glyph
145 // Glyph shapes are defined relative to a baseline, which is the
146 // bottom of uppercase characters. Characters extend both above
147 // and below the baseline.
150 // As you draw text to the screen, you keep track of a "current point"
151 // which is the origin of each character. The current point's vertical
152 // position is the baseline. Even "baked fonts" use this model.
154 // Vertical Font Metrics
155 // The vertical qualities of the font, used to vertically position
156 // and space the characters. See docs for stbtt_GetFontVMetrics.
158 // Font Size in Pixels or Points
159 // The preferred interface for specifying font sizes in stb_truetype
160 // is to specify how tall the font's vertical extent should be in pixels.
161 // If that sounds good enough, skip the next paragraph.
163 // Most font APIs instead use "points", which are a common typographic
164 // measurement for describing font size, defined as 72 points per inch.
165 // stb_truetype provides a point API for compatibility. However, true
166 // "per inch" conventions don't make much sense on computer displays
167 // since they different monitors have different number of pixels per
168 // inch. For example, Windows traditionally uses a convention that
169 // there are 96 pixels per inch, thus making 'inch' measurements have
170 // nothing to do with inches, and thus effectively defining a point to
171 // be 1.333 pixels. Additionally, the TrueType font data provides
172 // an explicit scale factor to scale a given font's glyphs to points,
173 // but the author has observed that this scale factor is often wrong
174 // for non-commercial fonts, thus making fonts scaled in points
175 // according to the TrueType spec incoherently sized in practice.
181 // - Use the functions with Subpixel at the end to allow your characters
182 // to have subpixel positioning. Since the font is anti-aliased, not
183 // hinted, this is very import for quality. (This is not possible with
186 // - Kerning is now supported, and if you're supporting subpixel rendering
187 // then kerning is worth using to give your text a polished look.
191 // - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
192 // if you don't do this, stb_truetype is forced to do the conversion on
195 // - There are a lot of memory allocations. We should modify it to take
196 // a temp buffer and allocate from the temp buffer (without freeing),
197 // should help performance a lot.
201 // The system uses the raw data found in the .ttf file without changing it
202 // and without building auxiliary data structures. This is a bit inefficient
203 // on little-endian systems (the data is big-endian), but assuming you're
204 // caching the bitmaps or glyph shapes this shouldn't be a big deal.
206 // It appears to be very hard to programmatically determine what font a
207 // given file is in a general way. I provide an API for this, but I don't
211 // SOURCE STATISTICS (based on v0.6c, 2050 LOC)
213 // Documentation & header file 520 LOC \___ 660 LOC documentation
214 // Sample code 140 LOC /
215 // Truetype parsing 620 LOC ---- 620 LOC TrueType
216 // Software rasterization 240 LOC \ .
217 // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
218 // Bitmap management 100 LOC /
219 // Baked bitmap interface 70 LOC /
220 // Font name matching & access 150 LOC ---- 150
221 // C runtime library abstraction 60 LOC ---- 60
224 //////////////////////////////////////////////////////////////////////////////
225 //////////////////////////////////////////////////////////////////////////////
230 // Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
233 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
234 #include "stb_truetype.h"
236 unsigned char ttf_buffer
[1<<20];
237 unsigned char temp_bitmap
[512*512];
239 stbtt_bakedchar cdata
[96]; // ASCII 32..126 is 95 glyphs
242 void my_stbtt_initfont(void)
244 fread(ttf_buffer
, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
245 stbtt_BakeFontBitmap(ttf_buffer
,0, 32.0, temp_bitmap
,512,512, 32,96, cdata
); // no guarantee this fits!
246 // can free ttf_buffer at this point
247 glGenTextures(1, &ftex
);
248 glBindTexture(GL_TEXTURE_2D
, ftex
);
249 glTexImage2D(GL_TEXTURE_2D
, 0, GL_ALPHA
, 512,512, 0, GL_ALPHA
, GL_UNSIGNED_BYTE
, temp_bitmap
);
250 // can free temp_bitmap at this point
251 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
254 void my_stbtt_print(float x
, float y
, char *text
)
256 // assume orthographic projection with units = screen pixels, origin at top left
257 glEnable(GL_TEXTURE_2D
);
258 glBindTexture(GL_TEXTURE_2D
, ftex
);
261 if (*text
>= 32 && *text
< 128) {
262 stbtt_aligned_quad q
;
263 stbtt_GetBakedQuad(cdata
, 512,512, *text
-32, &x
,&y
,&q
,1);//1=opengl & d3d10+,0=d3d9
264 glTexCoord2f(q
.s0
,q
.t1
); glVertex2f(q
.x0
,q
.y0
);
265 glTexCoord2f(q
.s1
,q
.t1
); glVertex2f(q
.x1
,q
.y0
);
266 glTexCoord2f(q
.s1
,q
.t0
); glVertex2f(q
.x1
,q
.y1
);
267 glTexCoord2f(q
.s0
,q
.t0
); glVertex2f(q
.x0
,q
.y1
);
276 //////////////////////////////////////////////////////////////////////////////
278 // Complete program (this compiles): get a single bitmap, print as ASCII art
282 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
283 #include "stb_truetype.h"
285 char ttf_buffer
[1<<25];
287 int main(int argc
, char **argv
)
290 unsigned char *bitmap
;
291 int w
,h
,i
,j
,c
= (argc
> 1 ? atoi(argv
[1]) : 'a'), s
= (argc
> 2 ? atoi(argv
[2]) : 20);
293 fread(ttf_buffer
, 1, 1<<25, fopen(argc
> 3 ? argv
[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
295 stbtt_InitFont(&font
, ttf_buffer
, stbtt_GetFontOffsetForIndex(ttf_buffer
,0));
296 bitmap
= stbtt_GetCodepointBitmap(&font
, 0,stbtt_ScaleForPixelHeight(&font
, s
), c
, &w
, &h
, 0,0);
298 for (j
=0; j
< h
; ++j
) {
299 for (i
=0; i
< w
; ++i
)
300 putchar(" .:ioVM@"[bitmap
[j
*w
+i
]>>5]);
320 //////////////////////////////////////////////////////////////////////////////
322 // Complete program: print "Hello World!" banner, with bugs
326 unsigned char screen
[20][79];
328 int main(int arg
, char **argv
)
331 int i
,j
,ascent
,baseline
,ch
=0;
332 float scale
, xpos
=2; // leave a little padding in case the character extends left
333 char *text
= "Heljo World!";
335 fread(buffer
, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
336 stbtt_InitFont(&font
, buffer
, 0);
338 scale
= stbtt_ScaleForPixelHeight(&font
, 15);
339 stbtt_GetFontVMetrics(&font
, &ascent
,0,0);
340 baseline
= (int) (ascent
*scale
);
343 int advance
,lsb
,x0
,y0
,x1
,y1
;
344 float x_shift
= xpos
- (float) floor(xpos
);
345 stbtt_GetCodepointHMetrics(&font
, text
[ch
], &advance
, &lsb
);
346 stbtt_GetCodepointBitmapBoxSubpixel(&font
, text
[ch
], scale
,scale
,x_shift
,0, &x0
,&y0
,&x1
,&y1
);
347 stbtt_MakeCodepointBitmapSubpixel(&font
, &screen
[baseline
+ y0
][(int) xpos
+ x0
], x1
-x0
,y1
-y0
, 79, scale
,scale
,x_shift
,0, text
[ch
]);
348 // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
349 // because this API is really for baking character bitmaps into textures. if you want to render
350 // a sequence of characters, you really need to render each bitmap to a temp buffer, then
351 // "alpha blend" that into the working buffer
352 xpos
+= (advance
* scale
);
354 xpos
+= scale
*stbtt_GetCodepointKernAdvance(&font
, text
[ch
],text
[ch
+1]);
358 for (j
=0; j
< 20; ++j
) {
359 for (i
=0; i
< 78; ++i
)
360 putchar(" .:ioVM@"[screen
[j
][i
]>>5]);
369 //////////////////////////////////////////////////////////////////////////////
370 //////////////////////////////////////////////////////////////////////////////
372 //// INTEGRATION WITH YOUR CODEBASE
374 //// The following sections allow you to supply alternate definitions
375 //// of C library functions used by stb_truetype.
377 #ifdef STB_TRUETYPE_IMPLEMENTATION
378 // #define your own (u)stbtt_int8/16/32 before including to override this
380 typedef unsigned char stbtt_uint8
;
381 typedef signed char stbtt_int8
;
382 typedef unsigned short stbtt_uint16
;
383 typedef signed short stbtt_int16
;
384 typedef unsigned int stbtt_uint32
;
385 typedef signed int stbtt_int32
;
388 typedef char stbtt__check_size32
[sizeof(stbtt_int32
)==4 ? 1 : -1];
389 typedef char stbtt__check_size16
[sizeof(stbtt_int16
)==2 ? 1 : -1];
391 // #define your own STBTT_sort() to override this to avoid qsort
394 #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
397 // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
400 #define STBTT_ifloor(x) ((int) floor(x))
401 #define STBTT_iceil(x) ((int) ceil(x))
406 #define STBTT_sqrt(x) sqrt(x)
409 // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
412 #define STBTT_malloc(x,u) ((void)(u),malloc(x))
413 #define STBTT_free(x,u) ((void)(u),free(x))
418 #define STBTT_assert(x) assert(x)
423 #define STBTT_strlen(x) strlen(x)
428 #define STBTT_memcpy memcpy
429 #define STBTT_memset memset
433 ///////////////////////////////////////////////////////////////////////////////
434 ///////////////////////////////////////////////////////////////////////////////
440 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
441 #define __STB_INCLUDE_STB_TRUETYPE_H__
444 #define STBTT_DEF static
446 #define STBTT_DEF extern
453 //////////////////////////////////////////////////////////////////////////////
455 // TEXTURE BAKING API
457 // If you use this API, you only have to call two functions ever.
462 unsigned short x0
,y0
,x1
,y1
; // coordinates of bbox in bitmap
463 float xoff
,yoff
,xadvance
;
466 STBTT_DEF
int stbtt_BakeFontBitmap(const unsigned char *data
, int offset
, // font location (use offset=0 for plain .ttf)
467 float pixel_height
, // height of font in pixels
468 unsigned char *pixels
, int pw
, int ph
, // bitmap to be filled in
469 int first_char
, int num_chars
, // characters to bake
470 stbtt_bakedchar
*chardata
); // you allocate this, it's num_chars long
471 // if return is positive, the first unused row of the bitmap
472 // if return is negative, returns the negative of the number of characters that fit
473 // if return is 0, no characters fit and no rows were used
474 // This uses a very crappy packing.
478 float x0
,y0
,s0
,t0
; // top-left
479 float x1
,y1
,s1
,t1
; // bottom-right
480 } stbtt_aligned_quad
;
482 STBTT_DEF
void stbtt_GetBakedQuad(stbtt_bakedchar
*chardata
, int pw
, int ph
, // same data as above
483 int char_index
, // character to display
484 float *xpos
, float *ypos
, // pointers to current position in screen pixel space
485 stbtt_aligned_quad
*q
, // output: quad to draw
486 int opengl_fillrule
); // true if opengl fill rule; false if DX9 or earlier
487 // Call GetBakedQuad with char_index = 'character - first_char', and it
488 // creates the quad you need to draw and advances the current position.
490 // The coordinate system used assumes y increases downwards.
492 // Characters will extend both above and below the current position;
493 // see discussion of "BASELINE" above.
495 // It's inefficient; you might want to c&p it and optimize it.
499 //////////////////////////////////////////////////////////////////////////////
501 // NEW TEXTURE BAKING API
503 // This provides options for packing multiple fonts into one atlas, not
504 // perfectly but better than nothing.
508 unsigned short x0
,y0
,x1
,y1
; // coordinates of bbox in bitmap
509 float xoff
,yoff
,xadvance
;
513 typedef struct stbtt_pack_context stbtt_pack_context
;
515 STBTT_DEF
int stbtt_PackBegin(stbtt_pack_context
*spc
, unsigned char *pixels
, int width
, int height
, int stride_in_bytes
, int padding
, void *alloc_context
);
516 // Initializes a packing context stored in the passed-in stbtt_pack_context.
517 // Future calls using this context will pack characters into the bitmap passed
518 // in here: a 1-channel bitmap that is weight x height. stride_in_bytes is
519 // the distance from one row to the next (or 0 to mean they are packed tightly
520 // together). "padding" is // the amount of padding to leave between each
521 // character (normally you want '1' for bitmaps you'll use as textures with
522 // bilinear filtering).
524 // Returns 0 on failure, 1 on success.
526 STBTT_DEF
void stbtt_PackEnd (stbtt_pack_context
*spc
);
527 // Cleans up the packing context and frees all memory.
529 #define STBTT_POINT_SIZE(x) (-(x))
531 STBTT_DEF
int stbtt_PackFontRange(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, float font_size
,
532 int first_unicode_char_in_range
, int num_chars_in_range
, stbtt_packedchar
*chardata_for_range
);
533 // Creates character bitmaps from the font_index'th font found in fontdata (use
534 // font_index=0 if you don't know what that is). It creates num_chars_in_range
535 // bitmaps for characters with unicode values starting at first_unicode_char_in_range
536 // and increasing. Data for how to render them is stored in chardata_for_range;
537 // pass these to stbtt_GetPackedQuad to get back renderable quads.
539 // font_size is the full height of the character from ascender to descender,
540 // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
541 // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
542 // and pass that result as 'font_size':
543 // ..., 20 , ... // font max minus min y is 20 pixels tall
544 // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
549 int first_unicode_char_in_range
;
550 int num_chars_in_range
;
551 stbtt_packedchar
*chardata_for_range
; // output
554 STBTT_DEF
int stbtt_PackFontRanges(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, stbtt_pack_range
*ranges
, int num_ranges
);
555 // Creates character bitmaps from multiple ranges of characters stored in
556 // ranges. This will usually create a better-packed bitmap than multiple
557 // calls to stbtt_PackFontRange.
560 STBTT_DEF
void stbtt_PackSetOversampling(stbtt_pack_context
*spc
, unsigned int h_oversample
, unsigned int v_oversample
);
561 // Oversampling a font increases the quality by allowing higher-quality subpixel
562 // positioning, and is especially valuable at smaller text sizes.
564 // This function sets the amount of oversampling for all following calls to
565 // stbtt_PackFontRange(s). The default (no oversampling) is achieved by
566 // h_oversample=1, v_oversample=1. The total number of pixels required is
567 // h_oversample*v_oversample larger than the default; for example, 2x2
568 // oversampling requires 4x the storage of 1x1. For best results, render
569 // oversampled textures with bilinear filtering. Look at the readme in
570 // stb/tests/oversample for information about oversampled fonts
572 STBTT_DEF
void stbtt_GetPackedQuad(stbtt_packedchar
*chardata
, int pw
, int ph
, // same data as above
573 int char_index
, // character to display
574 float *xpos
, float *ypos
, // pointers to current position in screen pixel space
575 stbtt_aligned_quad
*q
, // output: quad to draw
576 int align_to_integer
);
578 // this is an opaque structure that you shouldn't mess with which holds
579 // all the context needed from PackBegin to PackEnd.
580 struct stbtt_pack_context
{
581 void *user_allocator_context
;
587 unsigned int h_oversample
, v_oversample
;
588 unsigned char *pixels
;
592 //////////////////////////////////////////////////////////////////////////////
598 STBTT_DEF
int stbtt_GetFontOffsetForIndex(const unsigned char *data
, int index
);
599 // Each .ttf/.ttc file may have more than one font. Each font has a sequential
600 // index number starting from 0. Call this function to get the font offset for
601 // a given index; it returns -1 if the index is out of range. A regular .ttf
602 // file will only define one font and it always be at offset 0, so it will
603 // return '0' for index 0, and -1 for all other indices. You can just skip
604 // this step if you know it's that kind of font.
607 // The following structure is defined publically so you can declare one on
608 // the stack or as a global or etc, but you should treat it as opaque.
609 typedef struct stbtt_fontinfo
612 unsigned char * data
; // pointer to .ttf file
613 int fontstart
; // offset of start of font
615 int numGlyphs
; // number of glyphs, needed for range checking
617 int loca
,head
,glyf
,hhea
,hmtx
,kern
; // table locations as offset from start of .ttf
618 int index_map
; // a cmap mapping for our chosen character encoding
619 int indexToLocFormat
; // format needed to map from glyph index to glyph
622 STBTT_DEF
int stbtt_InitFont(stbtt_fontinfo
*info
, const unsigned char *data
, int offset
);
623 // Given an offset into the file that defines a font, this function builds
624 // the necessary cached info for the rest of the system. You must allocate
625 // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
626 // need to do anything special to free it, because the contents are pure
627 // value data with no additional data structures. Returns 0 on failure.
630 //////////////////////////////////////////////////////////////////////////////
632 // CHARACTER TO GLYPH-INDEX CONVERSIOn
634 STBTT_DEF
int stbtt_FindGlyphIndex(const stbtt_fontinfo
*info
, int unicode_codepoint
);
635 // If you're going to perform multiple operations on the same character
636 // and you want a speed-up, call this function with the character you're
637 // going to process, then use glyph-based functions instead of the
638 // codepoint-based functions.
641 //////////////////////////////////////////////////////////////////////////////
643 // CHARACTER PROPERTIES
646 STBTT_DEF
float stbtt_ScaleForPixelHeight(const stbtt_fontinfo
*info
, float pixels
);
647 // computes a scale factor to produce a font whose "height" is 'pixels' tall.
648 // Height is measured as the distance from the highest ascender to the lowest
649 // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
651 // scale = pixels / (ascent - descent)
652 // so if you prefer to measure height by the ascent only, use a similar calculation.
654 STBTT_DEF
float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo
*info
, float pixels
);
655 // computes a scale factor to produce a font whose EM size is mapped to
656 // 'pixels' tall. This is probably what traditional APIs compute, but
659 STBTT_DEF
void stbtt_GetFontVMetrics(const stbtt_fontinfo
*info
, int *ascent
, int *descent
, int *lineGap
);
660 // ascent is the coordinate above the baseline the font extends; descent
661 // is the coordinate below the baseline the font extends (i.e. it is typically negative)
662 // lineGap is the spacing between one row's descent and the next row's ascent...
663 // so you should advance the vertical position by "*ascent - *descent + *lineGap"
664 // these are expressed in unscaled coordinates, so you must multiply by
665 // the scale factor for a given size
667 STBTT_DEF
void stbtt_GetFontBoundingBox(const stbtt_fontinfo
*info
, int *x0
, int *y0
, int *x1
, int *y1
);
668 // the bounding box around all possible characters
670 STBTT_DEF
void stbtt_GetCodepointHMetrics(const stbtt_fontinfo
*info
, int codepoint
, int *advanceWidth
, int *leftSideBearing
);
671 // leftSideBearing is the offset from the current horizontal position to the left edge of the character
672 // advanceWidth is the offset from the current horizontal position to the next horizontal position
673 // these are expressed in unscaled coordinates
675 STBTT_DEF
int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo
*info
, int ch1
, int ch2
);
676 // an additional amount to add to the 'advance' value between ch1 and ch2
678 STBTT_DEF
int stbtt_GetCodepointBox(const stbtt_fontinfo
*info
, int codepoint
, int *x0
, int *y0
, int *x1
, int *y1
);
679 // Gets the bounding box of the visible part of the glyph, in unscaled coordinates
681 STBTT_DEF
void stbtt_GetGlyphHMetrics(const stbtt_fontinfo
*info
, int glyph_index
, int *advanceWidth
, int *leftSideBearing
);
682 STBTT_DEF
int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo
*info
, int glyph1
, int glyph2
);
683 STBTT_DEF
int stbtt_GetGlyphBox(const stbtt_fontinfo
*info
, int glyph_index
, int *x0
, int *y0
, int *x1
, int *y1
);
684 // as above, but takes one or more glyph indices for greater efficiency
687 //////////////////////////////////////////////////////////////////////////////
689 // GLYPH SHAPES (you probably don't need these, but they have to go before
690 // the bitmaps for C declaration-order reasons)
693 #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
701 #ifndef stbtt_vertex // you can predefine this to use different values
702 // (we share this with other code at RAD)
703 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
706 stbtt_vertex_type x
,y
,cx
,cy
;
707 unsigned char type
,padding
;
711 STBTT_DEF
int stbtt_IsGlyphEmpty(const stbtt_fontinfo
*info
, int glyph_index
);
712 // returns non-zero if nothing is drawn for this glyph
714 STBTT_DEF
int stbtt_GetCodepointShape(const stbtt_fontinfo
*info
, int unicode_codepoint
, stbtt_vertex
**vertices
);
715 STBTT_DEF
int stbtt_GetGlyphShape(const stbtt_fontinfo
*info
, int glyph_index
, stbtt_vertex
**vertices
);
716 // returns # of vertices and fills *vertices with the pointer to them
717 // these are expressed in "unscaled" coordinates
719 // The shape is a series of countours. Each one starts with
720 // a STBTT_moveto, then consists of a series of mixed
721 // STBTT_lineto and STBTT_curveto segments. A lineto
722 // draws a line from previous endpoint to its x,y; a curveto
723 // draws a quadratic bezier from previous endpoint to
724 // its x,y, using cx,cy as the bezier control point.
726 STBTT_DEF
void stbtt_FreeShape(const stbtt_fontinfo
*info
, stbtt_vertex
*vertices
);
727 // frees the data allocated above
729 //////////////////////////////////////////////////////////////////////////////
734 STBTT_DEF
void stbtt_FreeBitmap(unsigned char *bitmap
, void *userdata
);
735 // frees the bitmap allocated below
737 STBTT_DEF
unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, int codepoint
, int *width
, int *height
, int *xoff
, int *yoff
);
738 // allocates a large-enough single-channel 8bpp bitmap and renders the
739 // specified character/glyph at the specified scale into it, with
740 // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
741 // *width & *height are filled out with the width & height of the bitmap,
742 // which is stored left-to-right, top-to-bottom.
744 // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
746 STBTT_DEF
unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int codepoint
, int *width
, int *height
, int *xoff
, int *yoff
);
747 // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
748 // shift for the character
750 STBTT_DEF
void stbtt_MakeCodepointBitmap(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, int codepoint
);
751 // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
752 // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
753 // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
754 // width and height and positioning info for it first.
756 STBTT_DEF
void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int codepoint
);
757 // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
758 // shift for the character
760 STBTT_DEF
void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo
*font
, int codepoint
, float scale_x
, float scale_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
);
761 // get the bbox of the bitmap centered around the glyph origin; so the
762 // bitmap width is ix1-ix0, height is iy1-iy0, and location to place
763 // the bitmap top left is (leftSideBearing*scale,iy0).
764 // (Note that the bitmap uses y-increases-down, but the shape uses
765 // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
767 STBTT_DEF
void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo
*font
, int codepoint
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
);
768 // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
769 // shift for the character
771 // the following functions are equivalent to the above functions, but operate
772 // on glyph indices instead of Unicode codepoints (for efficiency)
773 STBTT_DEF
unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, int glyph
, int *width
, int *height
, int *xoff
, int *yoff
);
774 STBTT_DEF
unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int glyph
, int *width
, int *height
, int *xoff
, int *yoff
);
775 STBTT_DEF
void stbtt_MakeGlyphBitmap(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, int glyph
);
776 STBTT_DEF
void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int glyph
);
777 STBTT_DEF
void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo
*font
, int glyph
, float scale_x
, float scale_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
);
778 STBTT_DEF
void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo
*font
, int glyph
, float scale_x
, float scale_y
,float shift_x
, float shift_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
);
781 // @TODO: don't expose this structure
785 unsigned char *pixels
;
788 STBTT_DEF
void stbtt_Rasterize(stbtt__bitmap
*result
, float flatness_in_pixels
, stbtt_vertex
*vertices
, int num_verts
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int x_off
, int y_off
, int invert
, void *userdata
);
790 //////////////////////////////////////////////////////////////////////////////
792 // Finding the right font...
794 // You should really just solve this offline, keep your own tables
795 // of what font is what, and don't try to get it out of the .ttf file.
796 // That's because getting it out of the .ttf file is really hard, because
797 // the names in the file can appear in many possible encodings, in many
798 // possible languages, and e.g. if you need a case-insensitive comparison,
799 // the details of that depend on the encoding & language in a complex way
800 // (actually underspecified in truetype, but also gigantic).
802 // But you can use the provided functions in two possible ways:
803 // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
804 // unicode-encoded names to try to find the font you want;
805 // you can run this before calling stbtt_InitFont()
807 // stbtt_GetFontNameString() lets you get any of the various strings
808 // from the file yourself and do your own comparisons on them.
809 // You have to have called stbtt_InitFont() first.
812 STBTT_DEF
int stbtt_FindMatchingFont(const unsigned char *fontdata
, const char *name
, int flags
);
813 // returns the offset (not index) of the font that matches, or -1 if none
814 // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
815 // if you use any other flag, use a font name like "Arial"; this checks
816 // the 'macStyle' header field; i don't know if fonts set this consistently
817 #define STBTT_MACSTYLE_DONTCARE 0
818 #define STBTT_MACSTYLE_BOLD 1
819 #define STBTT_MACSTYLE_ITALIC 2
820 #define STBTT_MACSTYLE_UNDERSCORE 4
821 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
823 STBTT_DEF
int stbtt_CompareUTF8toUTF16_bigendian(const char *s1
, int len1
, const char *s2
, int len2
);
824 // returns 1/0 whether the first string interpreted as utf8 is identical to
825 // the second string interpreted as big-endian utf16... useful for strings from next func
827 STBTT_DEF
const char *stbtt_GetFontNameString(const stbtt_fontinfo
*font
, int *length
, int platformID
, int encodingID
, int languageID
, int nameID
);
828 // returns the string (which may be big-endian double byte, e.g. for unicode)
829 // and puts the length in bytes in *length.
831 // some of the values for the IDs are below; for more see the truetype spec:
832 // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
833 // http://www.microsoft.com/typography/otspec/name.htm
836 STBTT_PLATFORM_ID_UNICODE
=0,
837 STBTT_PLATFORM_ID_MAC
=1,
838 STBTT_PLATFORM_ID_ISO
=2,
839 STBTT_PLATFORM_ID_MICROSOFT
=3
842 enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
843 STBTT_UNICODE_EID_UNICODE_1_0
=0,
844 STBTT_UNICODE_EID_UNICODE_1_1
=1,
845 STBTT_UNICODE_EID_ISO_10646
=2,
846 STBTT_UNICODE_EID_UNICODE_2_0_BMP
=3,
847 STBTT_UNICODE_EID_UNICODE_2_0_FULL
=4
850 enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
851 STBTT_MS_EID_SYMBOL
=0,
852 STBTT_MS_EID_UNICODE_BMP
=1,
853 STBTT_MS_EID_SHIFTJIS
=2,
854 STBTT_MS_EID_UNICODE_FULL
=10
857 enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
858 STBTT_MAC_EID_ROMAN
=0, STBTT_MAC_EID_ARABIC
=4,
859 STBTT_MAC_EID_JAPANESE
=1, STBTT_MAC_EID_HEBREW
=5,
860 STBTT_MAC_EID_CHINESE_TRAD
=2, STBTT_MAC_EID_GREEK
=6,
861 STBTT_MAC_EID_KOREAN
=3, STBTT_MAC_EID_RUSSIAN
=7
864 enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
865 // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
866 STBTT_MS_LANG_ENGLISH
=0x0409, STBTT_MS_LANG_ITALIAN
=0x0410,
867 STBTT_MS_LANG_CHINESE
=0x0804, STBTT_MS_LANG_JAPANESE
=0x0411,
868 STBTT_MS_LANG_DUTCH
=0x0413, STBTT_MS_LANG_KOREAN
=0x0412,
869 STBTT_MS_LANG_FRENCH
=0x040c, STBTT_MS_LANG_RUSSIAN
=0x0419,
870 STBTT_MS_LANG_GERMAN
=0x0407, STBTT_MS_LANG_SPANISH
=0x0409,
871 STBTT_MS_LANG_HEBREW
=0x040d, STBTT_MS_LANG_SWEDISH
=0x041D
874 enum { // languageID for STBTT_PLATFORM_ID_MAC
875 STBTT_MAC_LANG_ENGLISH
=0 , STBTT_MAC_LANG_JAPANESE
=11,
876 STBTT_MAC_LANG_ARABIC
=12, STBTT_MAC_LANG_KOREAN
=23,
877 STBTT_MAC_LANG_DUTCH
=4 , STBTT_MAC_LANG_RUSSIAN
=32,
878 STBTT_MAC_LANG_FRENCH
=1 , STBTT_MAC_LANG_SPANISH
=6 ,
879 STBTT_MAC_LANG_GERMAN
=2 , STBTT_MAC_LANG_SWEDISH
=5 ,
880 STBTT_MAC_LANG_HEBREW
=10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED
=33,
881 STBTT_MAC_LANG_ITALIAN
=3 , STBTT_MAC_LANG_CHINESE_TRAD
=19
888 #endif // __STB_INCLUDE_STB_TRUETYPE_H__
890 ///////////////////////////////////////////////////////////////////////////////
891 ///////////////////////////////////////////////////////////////////////////////
897 #ifdef STB_TRUETYPE_IMPLEMENTATION
899 #ifndef STBTT_MAX_OVERSAMPLE
900 #define STBTT_MAX_OVERSAMPLE 8
903 typedef int stbtt__test_oversample_pow2
[(STBTT_MAX_OVERSAMPLE
& (STBTT_MAX_OVERSAMPLE
-1)) == 0 ? 1 : -1];
905 //////////////////////////////////////////////////////////////////////////
907 // accessors to parse data from file
910 // on platforms that don't allow misaligned reads, if we want to allow
911 // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
913 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
914 #define ttCHAR(p) (* (stbtt_int8 *) (p))
915 #define ttFixed(p) ttLONG(p)
917 #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
919 #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
920 #define ttSHORT(p) (* (stbtt_int16 *) (p))
921 #define ttULONG(p) (* (stbtt_uint32 *) (p))
922 #define ttLONG(p) (* (stbtt_int32 *) (p))
926 static stbtt_uint16
ttUSHORT(const stbtt_uint8
*p
) { return p
[0]*256 + p
[1]; }
927 static stbtt_int16
ttSHORT(const stbtt_uint8
*p
) { return p
[0]*256 + p
[1]; }
928 static stbtt_uint32
ttULONG(const stbtt_uint8
*p
) { return (p
[0]<<24) + (p
[1]<<16) + (p
[2]<<8) + p
[3]; }
929 static stbtt_int32
ttLONG(const stbtt_uint8
*p
) { return (p
[0]<<24) + (p
[1]<<16) + (p
[2]<<8) + p
[3]; }
933 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
934 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
936 static int stbtt__isfont(const stbtt_uint8
*font
)
938 // check the version number
939 if (stbtt_tag4(font
, '1',0,0,0)) return 1; // TrueType 1
940 if (stbtt_tag(font
, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
941 if (stbtt_tag(font
, "OTTO")) return 1; // OpenType with CFF
942 if (stbtt_tag4(font
, 0,1,0,0)) return 1; // OpenType 1.0
946 // @OPTIMIZE: binary search
947 static stbtt_uint32
stbtt__find_table(stbtt_uint8
*data
, stbtt_uint32 fontstart
, const char *tag
)
949 stbtt_int32 num_tables
= ttUSHORT(data
+fontstart
+4);
950 stbtt_uint32 tabledir
= fontstart
+ 12;
952 for (i
=0; i
< num_tables
; ++i
) {
953 stbtt_uint32 loc
= tabledir
+ 16*i
;
954 if (stbtt_tag(data
+loc
+0, tag
))
955 return ttULONG(data
+loc
+8);
960 STBTT_DEF
int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection
, int index
)
962 // if it's just a font, there's only one valid index
963 if (stbtt__isfont(font_collection
))
964 return index
== 0 ? 0 : -1;
966 // check if it's a TTC
967 if (stbtt_tag(font_collection
, "ttcf")) {
969 if (ttULONG(font_collection
+4) == 0x00010000 || ttULONG(font_collection
+4) == 0x00020000) {
970 stbtt_int32 n
= ttLONG(font_collection
+8);
973 return ttULONG(font_collection
+12+index
*14);
979 STBTT_DEF
int stbtt_InitFont(stbtt_fontinfo
*info
, const unsigned char *data2
, int fontstart
)
981 stbtt_uint8
*data
= (stbtt_uint8
*) data2
;
982 stbtt_uint32 cmap
, t
;
983 stbtt_int32 i
,numTables
;
986 info
->fontstart
= fontstart
;
988 cmap
= stbtt__find_table(data
, fontstart
, "cmap"); // required
989 info
->loca
= stbtt__find_table(data
, fontstart
, "loca"); // required
990 info
->head
= stbtt__find_table(data
, fontstart
, "head"); // required
991 info
->glyf
= stbtt__find_table(data
, fontstart
, "glyf"); // required
992 info
->hhea
= stbtt__find_table(data
, fontstart
, "hhea"); // required
993 info
->hmtx
= stbtt__find_table(data
, fontstart
, "hmtx"); // required
994 info
->kern
= stbtt__find_table(data
, fontstart
, "kern"); // not required
995 if (!cmap
|| !info
->loca
|| !info
->head
|| !info
->glyf
|| !info
->hhea
|| !info
->hmtx
)
998 t
= stbtt__find_table(data
, fontstart
, "maxp");
1000 info
->numGlyphs
= ttUSHORT(data
+t
+4);
1002 info
->numGlyphs
= 0xffff;
1004 // find a cmap encoding table we understand *now* to avoid searching
1005 // later. (todo: could make this installable)
1006 // the same regardless of glyph.
1007 numTables
= ttUSHORT(data
+ cmap
+ 2);
1008 info
->index_map
= 0;
1009 for (i
=0; i
< numTables
; ++i
) {
1010 stbtt_uint32 encoding_record
= cmap
+ 4 + 8 * i
;
1011 // find an encoding we understand:
1012 switch(ttUSHORT(data
+encoding_record
)) {
1013 case STBTT_PLATFORM_ID_MICROSOFT
:
1014 switch (ttUSHORT(data
+encoding_record
+2)) {
1015 case STBTT_MS_EID_UNICODE_BMP
:
1016 case STBTT_MS_EID_UNICODE_FULL
:
1018 info
->index_map
= cmap
+ ttULONG(data
+encoding_record
+4);
1022 case STBTT_PLATFORM_ID_UNICODE
:
1023 // Mac/iOS has these
1024 // all the encodingIDs are unicode, so we don't bother to check it
1025 info
->index_map
= cmap
+ ttULONG(data
+encoding_record
+4);
1029 if (info
->index_map
== 0)
1032 info
->indexToLocFormat
= ttUSHORT(data
+info
->head
+ 50);
1036 STBTT_DEF
int stbtt_FindGlyphIndex(const stbtt_fontinfo
*info
, int unicode_codepoint
)
1038 stbtt_uint8
*data
= info
->data
;
1039 stbtt_uint32 index_map
= info
->index_map
;
1041 stbtt_uint16 format
= ttUSHORT(data
+ index_map
+ 0);
1042 if (format
== 0) { // apple byte encoding
1043 stbtt_int32 bytes
= ttUSHORT(data
+ index_map
+ 2);
1044 if (unicode_codepoint
< bytes
-6)
1045 return ttBYTE(data
+ index_map
+ 6 + unicode_codepoint
);
1047 } else if (format
== 6) {
1048 stbtt_uint32 first
= ttUSHORT(data
+ index_map
+ 6);
1049 stbtt_uint32 count
= ttUSHORT(data
+ index_map
+ 8);
1050 if ((stbtt_uint32
) unicode_codepoint
>= first
&& (stbtt_uint32
) unicode_codepoint
< first
+count
)
1051 return ttUSHORT(data
+ index_map
+ 10 + (unicode_codepoint
- first
)*2);
1053 } else if (format
== 2) {
1054 STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
1056 } else if (format
== 4) { // standard mapping for windows fonts: binary search collection of ranges
1057 stbtt_uint16 segcount
= ttUSHORT(data
+index_map
+6) >> 1;
1058 stbtt_uint16 searchRange
= ttUSHORT(data
+index_map
+8) >> 1;
1059 stbtt_uint16 entrySelector
= ttUSHORT(data
+index_map
+10);
1060 stbtt_uint16 rangeShift
= ttUSHORT(data
+index_map
+12) >> 1;
1062 // do a binary search of the segments
1063 stbtt_uint32 endCount
= index_map
+ 14;
1064 stbtt_uint32 search
= endCount
;
1066 if (unicode_codepoint
> 0xffff)
1069 // they lie from endCount .. endCount + segCount
1070 // but searchRange is the nearest power of two, so...
1071 if (unicode_codepoint
>= ttUSHORT(data
+ search
+ rangeShift
*2))
1072 search
+= rangeShift
*2;
1074 // now decrement to bias correctly to find smallest
1076 while (entrySelector
) {
1079 end
= ttUSHORT(data
+ search
+ searchRange
*2);
1080 if (unicode_codepoint
> end
)
1081 search
+= searchRange
*2;
1087 stbtt_uint16 offset
, start
;
1088 stbtt_uint16 item
= (stbtt_uint16
) ((search
- endCount
) >> 1);
1090 STBTT_assert(unicode_codepoint
<= ttUSHORT(data
+ endCount
+ 2*item
));
1091 start
= ttUSHORT(data
+ index_map
+ 14 + segcount
*2 + 2 + 2*item
);
1092 if (unicode_codepoint
< start
)
1095 offset
= ttUSHORT(data
+ index_map
+ 14 + segcount
*6 + 2 + 2*item
);
1097 return (stbtt_uint16
) (unicode_codepoint
+ ttSHORT(data
+ index_map
+ 14 + segcount
*4 + 2 + 2*item
));
1099 return ttUSHORT(data
+ offset
+ (unicode_codepoint
-start
)*2 + index_map
+ 14 + segcount
*6 + 2 + 2*item
);
1101 } else if (format
== 12 || format
== 13) {
1102 stbtt_uint32 ngroups
= ttULONG(data
+index_map
+12);
1103 stbtt_int32 low
,high
;
1104 low
= 0; high
= (stbtt_int32
)ngroups
;
1105 // Binary search the right group.
1106 while (low
< high
) {
1107 stbtt_int32 mid
= low
+ ((high
-low
) >> 1); // rounds down, so low <= mid < high
1108 stbtt_uint32 start_char
= ttULONG(data
+index_map
+16+mid
*12);
1109 stbtt_uint32 end_char
= ttULONG(data
+index_map
+16+mid
*12+4);
1110 if ((stbtt_uint32
) unicode_codepoint
< start_char
)
1112 else if ((stbtt_uint32
) unicode_codepoint
> end_char
)
1115 stbtt_uint32 start_glyph
= ttULONG(data
+index_map
+16+mid
*12+8);
1117 return start_glyph
+ unicode_codepoint
-start_char
;
1118 else // format == 13
1122 return 0; // not found
1129 STBTT_DEF
int stbtt_GetCodepointShape(const stbtt_fontinfo
*info
, int unicode_codepoint
, stbtt_vertex
**vertices
)
1131 return stbtt_GetGlyphShape(info
, stbtt_FindGlyphIndex(info
, unicode_codepoint
), vertices
);
1134 static void stbtt_setvertex(stbtt_vertex
*v
, stbtt_uint8 type
, stbtt_int32 x
, stbtt_int32 y
, stbtt_int32 cx
, stbtt_int32 cy
)
1137 v
->x
= (stbtt_int16
) x
;
1138 v
->y
= (stbtt_int16
) y
;
1139 v
->cx
= (stbtt_int16
) cx
;
1140 v
->cy
= (stbtt_int16
) cy
;
1143 static int stbtt__GetGlyfOffset(const stbtt_fontinfo
*info
, int glyph_index
)
1147 if (glyph_index
>= info
->numGlyphs
) return -1; // glyph index out of range
1148 if (info
->indexToLocFormat
>= 2) return -1; // unknown index->glyph map format
1150 if (info
->indexToLocFormat
== 0) {
1151 g1
= info
->glyf
+ ttUSHORT(info
->data
+ info
->loca
+ glyph_index
* 2) * 2;
1152 g2
= info
->glyf
+ ttUSHORT(info
->data
+ info
->loca
+ glyph_index
* 2 + 2) * 2;
1154 g1
= info
->glyf
+ ttULONG (info
->data
+ info
->loca
+ glyph_index
* 4);
1155 g2
= info
->glyf
+ ttULONG (info
->data
+ info
->loca
+ glyph_index
* 4 + 4);
1158 return g1
==g2
? -1 : g1
; // if length is 0, return -1
1161 STBTT_DEF
int stbtt_GetGlyphBox(const stbtt_fontinfo
*info
, int glyph_index
, int *x0
, int *y0
, int *x1
, int *y1
)
1163 int g
= stbtt__GetGlyfOffset(info
, glyph_index
);
1164 if (g
< 0) return 0;
1166 if (x0
) *x0
= ttSHORT(info
->data
+ g
+ 2);
1167 if (y0
) *y0
= ttSHORT(info
->data
+ g
+ 4);
1168 if (x1
) *x1
= ttSHORT(info
->data
+ g
+ 6);
1169 if (y1
) *y1
= ttSHORT(info
->data
+ g
+ 8);
1173 STBTT_DEF
int stbtt_GetCodepointBox(const stbtt_fontinfo
*info
, int codepoint
, int *x0
, int *y0
, int *x1
, int *y1
)
1175 return stbtt_GetGlyphBox(info
, stbtt_FindGlyphIndex(info
,codepoint
), x0
,y0
,x1
,y1
);
1178 STBTT_DEF
int stbtt_IsGlyphEmpty(const stbtt_fontinfo
*info
, int glyph_index
)
1180 stbtt_int16 numberOfContours
;
1181 int g
= stbtt__GetGlyfOffset(info
, glyph_index
);
1182 if (g
< 0) return 1;
1183 numberOfContours
= ttSHORT(info
->data
+ g
);
1184 return numberOfContours
== 0;
1187 static int stbtt__close_shape(stbtt_vertex
*vertices
, int num_vertices
, int was_off
, int start_off
,
1188 stbtt_int32 sx
, stbtt_int32 sy
, stbtt_int32 scx
, stbtt_int32 scy
, stbtt_int32 cx
, stbtt_int32 cy
)
1192 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, (cx
+scx
)>>1, (cy
+scy
)>>1, cx
,cy
);
1193 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, sx
,sy
,scx
,scy
);
1196 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
,sx
,sy
,cx
,cy
);
1198 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vline
,sx
,sy
,0,0);
1200 return num_vertices
;
1203 STBTT_DEF
int stbtt_GetGlyphShape(const stbtt_fontinfo
*info
, int glyph_index
, stbtt_vertex
**pvertices
)
1205 stbtt_int16 numberOfContours
;
1206 stbtt_uint8
*endPtsOfContours
;
1207 stbtt_uint8
*data
= info
->data
;
1208 stbtt_vertex
*vertices
=0;
1210 int g
= stbtt__GetGlyfOffset(info
, glyph_index
);
1214 if (g
< 0) return 0;
1216 numberOfContours
= ttSHORT(data
+ g
);
1218 if (numberOfContours
> 0) {
1219 stbtt_uint8 flags
=0,flagcount
;
1220 stbtt_int32 ins
, i
,j
=0,m
,n
, next_move
, was_off
=0, off
, start_off
=0;
1221 stbtt_int32 x
,y
,cx
,cy
,sx
,sy
, scx
,scy
;
1222 stbtt_uint8
*points
;
1223 endPtsOfContours
= (data
+ g
+ 10);
1224 ins
= ttUSHORT(data
+ g
+ 10 + numberOfContours
* 2);
1225 points
= data
+ g
+ 10 + numberOfContours
* 2 + 2 + ins
;
1227 n
= 1+ttUSHORT(endPtsOfContours
+ numberOfContours
*2-2);
1229 m
= n
+ 2*numberOfContours
; // a loose bound on how many vertices we might need
1230 vertices
= (stbtt_vertex
*) STBTT_malloc(m
* sizeof(vertices
[0]), info
->userdata
);
1237 // in first pass, we load uninterpreted data into the allocated array
1238 // above, shifted to the end of the array so we won't overwrite it when
1239 // we create our final data starting from the front
1241 off
= m
- n
; // starting offset for uninterpreted data, regardless of how m ends up being calculated
1245 for (i
=0; i
< n
; ++i
) {
1246 if (flagcount
== 0) {
1249 flagcount
= *points
++;
1252 vertices
[off
+i
].type
= flags
;
1255 // now load x coordinates
1257 for (i
=0; i
< n
; ++i
) {
1258 flags
= vertices
[off
+i
].type
;
1260 stbtt_int16 dx
= *points
++;
1261 x
+= (flags
& 16) ? dx
: -dx
; // ???
1263 if (!(flags
& 16)) {
1264 x
= x
+ (stbtt_int16
) (points
[0]*256 + points
[1]);
1268 vertices
[off
+i
].x
= (stbtt_int16
) x
;
1271 // now load y coordinates
1273 for (i
=0; i
< n
; ++i
) {
1274 flags
= vertices
[off
+i
].type
;
1276 stbtt_int16 dy
= *points
++;
1277 y
+= (flags
& 32) ? dy
: -dy
; // ???
1279 if (!(flags
& 32)) {
1280 y
= y
+ (stbtt_int16
) (points
[0]*256 + points
[1]);
1284 vertices
[off
+i
].y
= (stbtt_int16
) y
;
1287 // now convert them to our format
1289 sx
= sy
= cx
= cy
= scx
= scy
= 0;
1290 for (i
=0; i
< n
; ++i
) {
1291 flags
= vertices
[off
+i
].type
;
1292 x
= (stbtt_int16
) vertices
[off
+i
].x
;
1293 y
= (stbtt_int16
) vertices
[off
+i
].y
;
1295 if (next_move
== i
) {
1297 num_vertices
= stbtt__close_shape(vertices
, num_vertices
, was_off
, start_off
, sx
,sy
,scx
,scy
,cx
,cy
);
1299 // now start the new one
1300 start_off
= !(flags
& 1);
1302 // if we start off with an off-curve point, then when we need to find a point on the curve
1303 // where we can start, and we need to save some state for when we wraparound.
1306 if (!(vertices
[off
+i
+1].type
& 1)) {
1307 // next point is also a curve point, so interpolate an on-point curve
1308 sx
= (x
+ (stbtt_int32
) vertices
[off
+i
+1].x
) >> 1;
1309 sy
= (y
+ (stbtt_int32
) vertices
[off
+i
+1].y
) >> 1;
1311 // otherwise just use the next point as our start point
1312 sx
= (stbtt_int32
) vertices
[off
+i
+1].x
;
1313 sy
= (stbtt_int32
) vertices
[off
+i
+1].y
;
1314 ++i
; // we're using point i+1 as the starting point, so skip it
1320 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vmove
,sx
,sy
,0,0);
1322 next_move
= 1 + ttUSHORT(endPtsOfContours
+j
*2);
1325 if (!(flags
& 1)) { // if it's a curve
1326 if (was_off
) // two off-curve control points in a row means interpolate an on-curve midpoint
1327 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, (cx
+x
)>>1, (cy
+y
)>>1, cx
, cy
);
1333 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, x
,y
, cx
, cy
);
1335 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vline
, x
,y
,0,0);
1340 num_vertices
= stbtt__close_shape(vertices
, num_vertices
, was_off
, start_off
, sx
,sy
,scx
,scy
,cx
,cy
);
1341 } else if (numberOfContours
== -1) {
1344 stbtt_uint8
*comp
= data
+ g
+ 10;
1348 stbtt_uint16 flags
, gidx
;
1349 int comp_num_verts
= 0, i
;
1350 stbtt_vertex
*comp_verts
= 0, *tmp
= 0;
1351 float mtx
[6] = {1,0,0,1,0,0}, m
, n
;
1353 flags
= ttSHORT(comp
); comp
+=2;
1354 gidx
= ttSHORT(comp
); comp
+=2;
1356 if (flags
& 2) { // XY values
1357 if (flags
& 1) { // shorts
1358 mtx
[4] = ttSHORT(comp
); comp
+=2;
1359 mtx
[5] = ttSHORT(comp
); comp
+=2;
1361 mtx
[4] = ttCHAR(comp
); comp
+=1;
1362 mtx
[5] = ttCHAR(comp
); comp
+=1;
1366 // @TODO handle matching point
1369 if (flags
& (1<<3)) { // WE_HAVE_A_SCALE
1370 mtx
[0] = mtx
[3] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1371 mtx
[1] = mtx
[2] = 0;
1372 } else if (flags
& (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
1373 mtx
[0] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1374 mtx
[1] = mtx
[2] = 0;
1375 mtx
[3] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1376 } else if (flags
& (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
1377 mtx
[0] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1378 mtx
[1] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1379 mtx
[2] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1380 mtx
[3] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1383 // Find transformation scales.
1384 m
= (float) STBTT_sqrt(mtx
[0]*mtx
[0] + mtx
[1]*mtx
[1]);
1385 n
= (float) STBTT_sqrt(mtx
[2]*mtx
[2] + mtx
[3]*mtx
[3]);
1387 // Get indexed glyph.
1388 comp_num_verts
= stbtt_GetGlyphShape(info
, gidx
, &comp_verts
);
1389 if (comp_num_verts
> 0) {
1390 // Transform vertices.
1391 for (i
= 0; i
< comp_num_verts
; ++i
) {
1392 stbtt_vertex
* v
= &comp_verts
[i
];
1393 stbtt_vertex_type x
,y
;
1395 v
->x
= (stbtt_vertex_type
)(m
* (mtx
[0]*x
+ mtx
[2]*y
+ mtx
[4]));
1396 v
->y
= (stbtt_vertex_type
)(n
* (mtx
[1]*x
+ mtx
[3]*y
+ mtx
[5]));
1398 v
->cx
= (stbtt_vertex_type
)(m
* (mtx
[0]*x
+ mtx
[2]*y
+ mtx
[4]));
1399 v
->cy
= (stbtt_vertex_type
)(n
* (mtx
[1]*x
+ mtx
[3]*y
+ mtx
[5]));
1402 tmp
= (stbtt_vertex
*)STBTT_malloc((num_vertices
+comp_num_verts
)*sizeof(stbtt_vertex
), info
->userdata
);
1404 if (vertices
) STBTT_free(vertices
, info
->userdata
);
1405 if (comp_verts
) STBTT_free(comp_verts
, info
->userdata
);
1408 if (num_vertices
> 0) STBTT_memcpy(tmp
, vertices
, num_vertices
*sizeof(stbtt_vertex
));
1409 STBTT_memcpy(tmp
+num_vertices
, comp_verts
, comp_num_verts
*sizeof(stbtt_vertex
));
1410 if (vertices
) STBTT_free(vertices
, info
->userdata
);
1412 STBTT_free(comp_verts
, info
->userdata
);
1413 num_vertices
+= comp_num_verts
;
1415 // More components ?
1416 more
= flags
& (1<<5);
1418 } else if (numberOfContours
< 0) {
1419 // @TODO other compound variations?
1422 // numberOfCounters == 0, do nothing
1425 *pvertices
= vertices
;
1426 return num_vertices
;
1429 STBTT_DEF
void stbtt_GetGlyphHMetrics(const stbtt_fontinfo
*info
, int glyph_index
, int *advanceWidth
, int *leftSideBearing
)
1431 stbtt_uint16 numOfLongHorMetrics
= ttUSHORT(info
->data
+info
->hhea
+ 34);
1432 if (glyph_index
< numOfLongHorMetrics
) {
1433 if (advanceWidth
) *advanceWidth
= ttSHORT(info
->data
+ info
->hmtx
+ 4*glyph_index
);
1434 if (leftSideBearing
) *leftSideBearing
= ttSHORT(info
->data
+ info
->hmtx
+ 4*glyph_index
+ 2);
1436 if (advanceWidth
) *advanceWidth
= ttSHORT(info
->data
+ info
->hmtx
+ 4*(numOfLongHorMetrics
-1));
1437 if (leftSideBearing
) *leftSideBearing
= ttSHORT(info
->data
+ info
->hmtx
+ 4*numOfLongHorMetrics
+ 2*(glyph_index
- numOfLongHorMetrics
));
1441 STBTT_DEF
int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo
*info
, int glyph1
, int glyph2
)
1443 stbtt_uint8
*data
= info
->data
+ info
->kern
;
1444 stbtt_uint32 needle
, straw
;
1447 // we only look at the first table. it must be 'horizontal' and format 0.
1450 if (ttUSHORT(data
+2) < 1) // number of tables, need at least 1
1452 if (ttUSHORT(data
+8) != 1) // horizontal flag must be set in format
1456 r
= ttUSHORT(data
+10) - 1;
1457 needle
= glyph1
<< 16 | glyph2
;
1460 straw
= ttULONG(data
+18+(m
*6)); // note: unaligned read
1463 else if (needle
> straw
)
1466 return ttSHORT(data
+22+(m
*6));
1471 STBTT_DEF
int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo
*info
, int ch1
, int ch2
)
1473 if (!info
->kern
) // if no kerning table, don't waste time looking up both codepoint->glyphs
1475 return stbtt_GetGlyphKernAdvance(info
, stbtt_FindGlyphIndex(info
,ch1
), stbtt_FindGlyphIndex(info
,ch2
));
1478 STBTT_DEF
void stbtt_GetCodepointHMetrics(const stbtt_fontinfo
*info
, int codepoint
, int *advanceWidth
, int *leftSideBearing
)
1480 stbtt_GetGlyphHMetrics(info
, stbtt_FindGlyphIndex(info
,codepoint
), advanceWidth
, leftSideBearing
);
1483 STBTT_DEF
void stbtt_GetFontVMetrics(const stbtt_fontinfo
*info
, int *ascent
, int *descent
, int *lineGap
)
1485 if (ascent
) *ascent
= ttSHORT(info
->data
+info
->hhea
+ 4);
1486 if (descent
) *descent
= ttSHORT(info
->data
+info
->hhea
+ 6);
1487 if (lineGap
) *lineGap
= ttSHORT(info
->data
+info
->hhea
+ 8);
1490 STBTT_DEF
void stbtt_GetFontBoundingBox(const stbtt_fontinfo
*info
, int *x0
, int *y0
, int *x1
, int *y1
)
1492 *x0
= ttSHORT(info
->data
+ info
->head
+ 36);
1493 *y0
= ttSHORT(info
->data
+ info
->head
+ 38);
1494 *x1
= ttSHORT(info
->data
+ info
->head
+ 40);
1495 *y1
= ttSHORT(info
->data
+ info
->head
+ 42);
1498 STBTT_DEF
float stbtt_ScaleForPixelHeight(const stbtt_fontinfo
*info
, float height
)
1500 int fheight
= ttSHORT(info
->data
+ info
->hhea
+ 4) - ttSHORT(info
->data
+ info
->hhea
+ 6);
1501 return (float) height
/ fheight
;
1504 STBTT_DEF
float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo
*info
, float pixels
)
1506 int unitsPerEm
= ttUSHORT(info
->data
+ info
->head
+ 18);
1507 return pixels
/ unitsPerEm
;
1510 STBTT_DEF
void stbtt_FreeShape(const stbtt_fontinfo
*info
, stbtt_vertex
*v
)
1512 STBTT_free(v
, info
->userdata
);
1515 //////////////////////////////////////////////////////////////////////////////
1517 // antialiasing software rasterizer
1520 STBTT_DEF
void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo
*font
, int glyph
, float scale_x
, float scale_y
,float shift_x
, float shift_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
)
1523 if (!stbtt_GetGlyphBox(font
, glyph
, &x0
,&y0
,&x1
,&y1
)) {
1524 // e.g. space character
1530 // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
1531 if (ix0
) *ix0
= STBTT_ifloor( x0
* scale_x
+ shift_x
);
1532 if (iy0
) *iy0
= STBTT_ifloor(-y1
* scale_y
+ shift_y
);
1533 if (ix1
) *ix1
= STBTT_iceil ( x1
* scale_x
+ shift_x
);
1534 if (iy1
) *iy1
= STBTT_iceil (-y0
* scale_y
+ shift_y
);
1538 STBTT_DEF
void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo
*font
, int glyph
, float scale_x
, float scale_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
)
1540 stbtt_GetGlyphBitmapBoxSubpixel(font
, glyph
, scale_x
, scale_y
,0.0f
,0.0f
, ix0
, iy0
, ix1
, iy1
);
1543 STBTT_DEF
void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo
*font
, int codepoint
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
)
1545 stbtt_GetGlyphBitmapBoxSubpixel(font
, stbtt_FindGlyphIndex(font
,codepoint
), scale_x
, scale_y
,shift_x
,shift_y
, ix0
,iy0
,ix1
,iy1
);
1548 STBTT_DEF
void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo
*font
, int codepoint
, float scale_x
, float scale_y
, int *ix0
, int *iy0
, int *ix1
, int *iy1
)
1550 stbtt_GetCodepointBitmapBoxSubpixel(font
, codepoint
, scale_x
, scale_y
,0.0f
,0.0f
, ix0
,iy0
,ix1
,iy1
);
1553 typedef struct stbtt__edge
{
1558 typedef struct stbtt__active_edge
1562 struct stbtt__active_edge
*next
;
1564 } stbtt__active_edge
;
1567 #define FIX (1 << FIXSHIFT)
1568 #define FIXMASK (FIX-1)
1570 static stbtt__active_edge
*new_active(stbtt__edge
*e
, int off_x
, float start_point
, void *userdata
)
1572 stbtt__active_edge
*z
= (stbtt__active_edge
*) STBTT_malloc(sizeof(*z
), userdata
); // @TODO: make a pool of these!!!
1573 float dxdy
= (e
->x1
- e
->x0
) / (e
->y1
- e
->y0
);
1574 STBTT_assert(e
->y0
<= start_point
);
1576 // round dx down to avoid going too far
1578 z
->dx
= -STBTT_ifloor(FIX
* -dxdy
);
1580 z
->dx
= STBTT_ifloor(FIX
* dxdy
);
1581 z
->x
= STBTT_ifloor(FIX
* (e
->x0
+ dxdy
* (start_point
- e
->y0
)));
1582 z
->x
-= off_x
* FIX
;
1585 z
->valid
= e
->invert
? 1 : -1;
1589 // note: this routine clips fills that extend off the edges... ideally this
1590 // wouldn't happen, but it could happen if the truetype glyph bounding boxes
1591 // are wrong, or if the user supplies a too-small bitmap
1592 static void stbtt__fill_active_edges(unsigned char *scanline
, int len
, stbtt__active_edge
*e
, int max_weight
)
1594 // non-zero winding fill
1599 // if we're currently at zero, we need to record the edge start point
1600 x0
= e
->x
; w
+= e
->valid
;
1602 int x1
= e
->x
; w
+= e
->valid
;
1603 // if we went to zero, we need to draw
1605 int i
= x0
>> FIXSHIFT
;
1606 int j
= x1
>> FIXSHIFT
;
1608 if (i
< len
&& j
>= 0) {
1610 // x0,x1 are the same pixel, so compute combined coverage
1611 scanline
[i
] = scanline
[i
] + (stbtt_uint8
) ((x1
- x0
) * max_weight
>> FIXSHIFT
);
1613 if (i
>= 0) // add antialiasing for x0
1614 scanline
[i
] = scanline
[i
] + (stbtt_uint8
) (((FIX
- (x0
& FIXMASK
)) * max_weight
) >> FIXSHIFT
);
1618 if (j
< len
) // add antialiasing for x1
1619 scanline
[j
] = scanline
[j
] + (stbtt_uint8
) (((x1
& FIXMASK
) * max_weight
) >> FIXSHIFT
);
1623 for (++i
; i
< j
; ++i
) // fill pixels between x0 and x1
1624 scanline
[i
] = scanline
[i
] + (stbtt_uint8
) max_weight
;
1634 static void stbtt__rasterize_sorted_edges(stbtt__bitmap
*result
, stbtt__edge
*e
, int n
, int vsubsample
, int off_x
, int off_y
, void *userdata
)
1636 stbtt__active_edge
*active
= NULL
;
1638 int max_weight
= (255 / vsubsample
); // weight per vertical scanline
1639 int s
; // vertical subsample index
1640 unsigned char scanline_data
[512], *scanline
;
1642 if (result
->w
> 512)
1643 scanline
= (unsigned char *) STBTT_malloc(result
->w
, userdata
);
1645 scanline
= scanline_data
;
1647 y
= off_y
* vsubsample
;
1648 e
[n
].y0
= (off_y
+ result
->h
) * (float) vsubsample
+ 1;
1650 while (j
< result
->h
) {
1651 STBTT_memset(scanline
, 0, result
->w
);
1652 for (s
=0; s
< vsubsample
; ++s
) {
1653 // find center of pixel for this scanline
1654 float scan_y
= y
+ 0.5f
;
1655 stbtt__active_edge
**step
= &active
;
1657 // update all active edges;
1658 // remove all active edges that terminate before the center of this scanline
1660 stbtt__active_edge
* z
= *step
;
1661 if (z
->ey
<= scan_y
) {
1662 *step
= z
->next
; // delete from list
1663 STBTT_assert(z
->valid
);
1665 STBTT_free(z
, userdata
);
1667 z
->x
+= z
->dx
; // advance to position for current scanline
1668 step
= &((*step
)->next
); // advance through list
1672 // resort the list if needed
1676 while (*step
&& (*step
)->next
) {
1677 if ((*step
)->x
> (*step
)->next
->x
) {
1678 stbtt__active_edge
*t
= *step
;
1679 stbtt__active_edge
*q
= t
->next
;
1686 step
= &(*step
)->next
;
1688 if (!changed
) break;
1691 // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
1692 while (e
->y0
<= scan_y
) {
1693 if (e
->y1
> scan_y
) {
1694 stbtt__active_edge
*z
= new_active(e
, off_x
, scan_y
, userdata
);
1695 // find insertion point
1698 else if (z
->x
< active
->x
) {
1703 // find thing to insert AFTER
1704 stbtt__active_edge
*p
= active
;
1705 while (p
->next
&& p
->next
->x
< z
->x
)
1707 // at this point, p->next->x is NOT < z->x
1715 // now process all active edges in XOR fashion
1717 stbtt__fill_active_edges(scanline
, result
->w
, active
, max_weight
);
1721 STBTT_memcpy(result
->pixels
+ j
* result
->stride
, scanline
, result
->w
);
1726 stbtt__active_edge
*z
= active
;
1727 active
= active
->next
;
1728 STBTT_free(z
, userdata
);
1731 if (scanline
!= scanline_data
)
1732 STBTT_free(scanline
, userdata
);
1735 static int stbtt__edge_compare(const void *p
, const void *q
)
1737 stbtt__edge
*a
= (stbtt__edge
*) p
;
1738 stbtt__edge
*b
= (stbtt__edge
*) q
;
1740 if (a
->y0
< b
->y0
) return -1;
1741 if (a
->y0
> b
->y0
) return 1;
1750 static 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
)
1752 float y_scale_inv
= invert
? -scale_y
: scale_y
;
1755 int vsubsample
= result
->h
< 8 ? 15 : 5;
1756 // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
1758 // now we have to blow out the windings into explicit edge lists
1760 for (i
=0; i
< windings
; ++i
)
1763 e
= (stbtt__edge
*) STBTT_malloc(sizeof(*e
) * (n
+1), userdata
); // add an extra one as a sentinel
1768 for (i
=0; i
< windings
; ++i
) {
1769 stbtt__point
*p
= pts
+ m
;
1772 for (k
=0; k
< wcount
[i
]; j
=k
++) {
1774 // skip the edge if horizontal
1775 if (p
[j
].y
== p
[k
].y
)
1777 // add edge from j to k to the list
1779 if (invert
? p
[j
].y
> p
[k
].y
: p
[j
].y
< p
[k
].y
) {
1783 e
[n
].x0
= p
[a
].x
* scale_x
+ shift_x
;
1784 e
[n
].y0
= (p
[a
].y
* y_scale_inv
+ shift_y
) * vsubsample
;
1785 e
[n
].x1
= p
[b
].x
* scale_x
+ shift_x
;
1786 e
[n
].y1
= (p
[b
].y
* y_scale_inv
+ shift_y
) * vsubsample
;
1791 // now sort the edges by their highest point (should snap to integer, and then by x)
1792 STBTT_sort(e
, n
, sizeof(e
[0]), stbtt__edge_compare
);
1794 // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
1795 stbtt__rasterize_sorted_edges(result
, e
, n
, vsubsample
, off_x
, off_y
, userdata
);
1797 STBTT_free(e
, userdata
);
1800 static void stbtt__add_point(stbtt__point
*points
, int n
, float x
, float y
)
1802 if (!points
) return; // during first pass, it's unallocated
1807 // tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
1808 static 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
)
1811 float mx
= (x0
+ 2*x1
+ x2
)/4;
1812 float my
= (y0
+ 2*y1
+ y2
)/4;
1813 // versus directly drawn line
1814 float dx
= (x0
+x2
)/2 - mx
;
1815 float dy
= (y0
+y2
)/2 - my
;
1816 if (n
> 16) // 65536 segments on one curve better be enough!
1818 if (dx
*dx
+dy
*dy
> objspace_flatness_squared
) { // half-pixel error allowed... need to be smaller if AA
1819 stbtt__tesselate_curve(points
, num_points
, x0
,y0
, (x0
+x1
)/2.0f
,(y0
+y1
)/2.0f
, mx
,my
, objspace_flatness_squared
,n
+1);
1820 stbtt__tesselate_curve(points
, num_points
, mx
,my
, (x1
+x2
)/2.0f
,(y1
+y2
)/2.0f
, x2
,y2
, objspace_flatness_squared
,n
+1);
1822 stbtt__add_point(points
, *num_points
,x2
,y2
);
1823 *num_points
= *num_points
+1;
1828 // returns number of contours
1829 static stbtt__point
*stbtt_FlattenCurves(stbtt_vertex
*vertices
, int num_verts
, float objspace_flatness
, int **contour_lengths
, int *num_contours
, void *userdata
)
1831 stbtt__point
*points
=0;
1834 float objspace_flatness_squared
= objspace_flatness
* objspace_flatness
;
1835 int i
,n
=0,start
=0, pass
;
1837 // count how many "moves" there are to get the contour count
1838 for (i
=0; i
< num_verts
; ++i
)
1839 if (vertices
[i
].type
== STBTT_vmove
)
1843 if (n
== 0) return 0;
1845 *contour_lengths
= (int *) STBTT_malloc(sizeof(**contour_lengths
) * n
, userdata
);
1847 if (*contour_lengths
== 0) {
1852 // make two passes through the points so we don't need to realloc
1853 for (pass
=0; pass
< 2; ++pass
) {
1856 points
= (stbtt__point
*) STBTT_malloc(num_points
* sizeof(points
[0]), userdata
);
1857 if (points
== NULL
) goto error
;
1861 for (i
=0; i
< num_verts
; ++i
) {
1862 switch (vertices
[i
].type
) {
1864 // start the next contour
1866 (*contour_lengths
)[n
] = num_points
- start
;
1870 x
= vertices
[i
].x
, y
= vertices
[i
].y
;
1871 stbtt__add_point(points
, num_points
++, x
,y
);
1874 x
= vertices
[i
].x
, y
= vertices
[i
].y
;
1875 stbtt__add_point(points
, num_points
++, x
, y
);
1878 stbtt__tesselate_curve(points
, &num_points
, x
,y
,
1879 vertices
[i
].cx
, vertices
[i
].cy
,
1880 vertices
[i
].x
, vertices
[i
].y
,
1881 objspace_flatness_squared
, 0);
1882 x
= vertices
[i
].x
, y
= vertices
[i
].y
;
1886 (*contour_lengths
)[n
] = num_points
- start
;
1891 STBTT_free(points
, userdata
);
1892 STBTT_free(*contour_lengths
, userdata
);
1893 *contour_lengths
= 0;
1898 STBTT_DEF
void stbtt_Rasterize(stbtt__bitmap
*result
, float flatness_in_pixels
, stbtt_vertex
*vertices
, int num_verts
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int x_off
, int y_off
, int invert
, void *userdata
)
1900 float scale
= scale_x
> scale_y
? scale_y
: scale_x
;
1901 int winding_count
, *winding_lengths
;
1902 stbtt__point
*windings
= stbtt_FlattenCurves(vertices
, num_verts
, flatness_in_pixels
/ scale
, &winding_lengths
, &winding_count
, userdata
);
1904 stbtt__rasterize(result
, windings
, winding_lengths
, winding_count
, scale_x
, scale_y
, shift_x
, shift_y
, x_off
, y_off
, invert
, userdata
);
1905 STBTT_free(winding_lengths
, userdata
);
1906 STBTT_free(windings
, userdata
);
1910 STBTT_DEF
void stbtt_FreeBitmap(unsigned char *bitmap
, void *userdata
)
1912 STBTT_free(bitmap
, userdata
);
1915 STBTT_DEF
unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int glyph
, int *width
, int *height
, int *xoff
, int *yoff
)
1917 int ix0
,iy0
,ix1
,iy1
;
1919 stbtt_vertex
*vertices
;
1920 int num_verts
= stbtt_GetGlyphShape(info
, glyph
, &vertices
);
1922 if (scale_x
== 0) scale_x
= scale_y
;
1924 if (scale_x
== 0) return NULL
;
1928 stbtt_GetGlyphBitmapBoxSubpixel(info
, glyph
, scale_x
, scale_y
, shift_x
, shift_y
, &ix0
,&iy0
,&ix1
,&iy1
);
1930 // now we get the size
1931 gbm
.w
= (ix1
- ix0
);
1932 gbm
.h
= (iy1
- iy0
);
1933 gbm
.pixels
= NULL
; // in case we error
1935 if (width
) *width
= gbm
.w
;
1936 if (height
) *height
= gbm
.h
;
1937 if (xoff
) *xoff
= ix0
;
1938 if (yoff
) *yoff
= iy0
;
1940 if (gbm
.w
&& gbm
.h
) {
1941 gbm
.pixels
= (unsigned char *) STBTT_malloc(gbm
.w
* gbm
.h
, info
->userdata
);
1945 stbtt_Rasterize(&gbm
, 0.35f
, vertices
, num_verts
, scale_x
, scale_y
, shift_x
, shift_y
, ix0
, iy0
, 1, info
->userdata
);
1948 STBTT_free(vertices
, info
->userdata
);
1952 STBTT_DEF
unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, int glyph
, int *width
, int *height
, int *xoff
, int *yoff
)
1954 return stbtt_GetGlyphBitmapSubpixel(info
, scale_x
, scale_y
, 0.0f
, 0.0f
, glyph
, width
, height
, xoff
, yoff
);
1957 STBTT_DEF
void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int glyph
)
1960 stbtt_vertex
*vertices
;
1961 int num_verts
= stbtt_GetGlyphShape(info
, glyph
, &vertices
);
1964 stbtt_GetGlyphBitmapBoxSubpixel(info
, glyph
, scale_x
, scale_y
, shift_x
, shift_y
, &ix0
,&iy0
,0,0);
1965 gbm
.pixels
= output
;
1968 gbm
.stride
= out_stride
;
1971 stbtt_Rasterize(&gbm
, 0.35f
, vertices
, num_verts
, scale_x
, scale_y
, shift_x
, shift_y
, ix0
,iy0
, 1, info
->userdata
);
1973 STBTT_free(vertices
, info
->userdata
);
1976 STBTT_DEF
void stbtt_MakeGlyphBitmap(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, int glyph
)
1978 stbtt_MakeGlyphBitmapSubpixel(info
, output
, out_w
, out_h
, out_stride
, scale_x
, scale_y
, 0.0f
,0.0f
, glyph
);
1981 STBTT_DEF
unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int codepoint
, int *width
, int *height
, int *xoff
, int *yoff
)
1983 return stbtt_GetGlyphBitmapSubpixel(info
, scale_x
, scale_y
,shift_x
,shift_y
, stbtt_FindGlyphIndex(info
,codepoint
), width
,height
,xoff
,yoff
);
1986 STBTT_DEF
void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, float shift_x
, float shift_y
, int codepoint
)
1988 stbtt_MakeGlyphBitmapSubpixel(info
, output
, out_w
, out_h
, out_stride
, scale_x
, scale_y
, shift_x
, shift_y
, stbtt_FindGlyphIndex(info
,codepoint
));
1991 STBTT_DEF
unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo
*info
, float scale_x
, float scale_y
, int codepoint
, int *width
, int *height
, int *xoff
, int *yoff
)
1993 return stbtt_GetCodepointBitmapSubpixel(info
, scale_x
, scale_y
, 0.0f
,0.0f
, codepoint
, width
,height
,xoff
,yoff
);
1996 STBTT_DEF
void stbtt_MakeCodepointBitmap(const stbtt_fontinfo
*info
, unsigned char *output
, int out_w
, int out_h
, int out_stride
, float scale_x
, float scale_y
, int codepoint
)
1998 stbtt_MakeCodepointBitmapSubpixel(info
, output
, out_w
, out_h
, out_stride
, scale_x
, scale_y
, 0.0f
,0.0f
, codepoint
);
2001 //////////////////////////////////////////////////////////////////////////////
2005 // This is SUPER-CRAPPY packing to keep source code small
2007 STBTT_DEF
int stbtt_BakeFontBitmap(const unsigned char *data
, int offset
, // font location (use offset=0 for plain .ttf)
2008 float pixel_height
, // height of font in pixels
2009 unsigned char *pixels
, int pw
, int ph
, // bitmap to be filled in
2010 int first_char
, int num_chars
, // characters to bake
2011 stbtt_bakedchar
*chardata
)
2014 int x
,y
,bottom_y
, i
;
2016 if (!stbtt_InitFont(&f
, data
, offset
))
2018 STBTT_memset(pixels
, 0, pw
*ph
); // background of 0 around pixels
2022 scale
= stbtt_ScaleForPixelHeight(&f
, pixel_height
);
2024 for (i
=0; i
< num_chars
; ++i
) {
2025 int advance
, lsb
, x0
,y0
,x1
,y1
,gw
,gh
;
2026 int g
= stbtt_FindGlyphIndex(&f
, first_char
+ i
);
2027 stbtt_GetGlyphHMetrics(&f
, g
, &advance
, &lsb
);
2028 stbtt_GetGlyphBitmapBox(&f
, g
, scale
,scale
, &x0
,&y0
,&x1
,&y1
);
2031 if (x
+ gw
+ 1 >= pw
)
2032 y
= bottom_y
, x
= 1; // advance to next row
2033 if (y
+ gh
+ 1 >= ph
) // check if it fits vertically AFTER potentially moving to next row
2035 STBTT_assert(x
+gw
< pw
);
2036 STBTT_assert(y
+gh
< ph
);
2037 stbtt_MakeGlyphBitmap(&f
, pixels
+x
+y
*pw
, gw
,gh
,pw
, scale
,scale
, g
);
2038 chardata
[i
].x0
= (stbtt_int16
) x
;
2039 chardata
[i
].y0
= (stbtt_int16
) y
;
2040 chardata
[i
].x1
= (stbtt_int16
) (x
+ gw
);
2041 chardata
[i
].y1
= (stbtt_int16
) (y
+ gh
);
2042 chardata
[i
].xadvance
= scale
* advance
;
2043 chardata
[i
].xoff
= (float) x0
;
2044 chardata
[i
].yoff
= (float) y0
;
2046 if (y
+gh
+1 > bottom_y
)
2052 STBTT_DEF
void stbtt_GetBakedQuad(stbtt_bakedchar
*chardata
, int pw
, int ph
, int char_index
, float *xpos
, float *ypos
, stbtt_aligned_quad
*q
, int opengl_fillrule
)
2054 float d3d_bias
= opengl_fillrule
? 0 : -0.5f
;
2055 float ipw
= 1.0f
/ pw
, iph
= 1.0f
/ ph
;
2056 stbtt_bakedchar
*b
= chardata
+ char_index
;
2057 int round_x
= STBTT_ifloor((*xpos
+ b
->xoff
) + 0.5f
);
2058 int round_y
= STBTT_ifloor((*ypos
+ b
->yoff
) + 0.5f
);
2060 q
->x0
= round_x
+ d3d_bias
;
2061 q
->y0
= round_y
+ d3d_bias
;
2062 q
->x1
= round_x
+ b
->x1
- b
->x0
+ d3d_bias
;
2063 q
->y1
= round_y
+ b
->y1
- b
->y0
+ d3d_bias
;
2065 q
->s0
= b
->x0
* ipw
;
2066 q
->t0
= b
->y0
* iph
;
2067 q
->s1
= b
->x1
* ipw
;
2068 q
->t1
= b
->y1
* iph
;
2070 *xpos
+= b
->xadvance
;
2073 //////////////////////////////////////////////////////////////////////////////
2075 // rectangle packing replacement routines if you don't have stb_rect_pack.h
2078 #ifndef STB_RECT_PACK_VERSION
2080 #define STBTT__NOTUSED(v) (void)(v)
2082 #define STBTT__NOTUSED(v) (void)sizeof(v)
2085 typedef int stbrp_coord
;
2087 ////////////////////////////////////////////////////////////////////////////////////
2090 // COMPILER WARNING ?!?!? //
2093 // if you get a compile warning due to these symbols being defined more than //
2094 // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
2096 ////////////////////////////////////////////////////////////////////////////////////
2112 int id
,w
,h
,was_packed
;
2115 static void stbrp_init_target(stbrp_context
*con
, int pw
, int ph
, stbrp_node
*nodes
, int num_nodes
)
2122 STBTT__NOTUSED(nodes
);
2123 STBTT__NOTUSED(num_nodes
);
2126 static void stbrp_pack_rects(stbrp_context
*con
, stbrp_rect
*rects
, int num_rects
)
2129 for (i
=0; i
< num_rects
; ++i
) {
2130 if (con
->x
+ rects
[i
].w
> con
->width
) {
2132 con
->y
= con
->bottom_y
;
2134 if (con
->y
+ rects
[i
].h
> con
->height
)
2136 rects
[i
].x
= con
->x
;
2137 rects
[i
].y
= con
->y
;
2138 rects
[i
].was_packed
= 1;
2139 con
->x
+= rects
[i
].w
;
2140 if (con
->y
+ rects
[i
].h
> con
->bottom_y
)
2141 con
->bottom_y
= con
->y
+ rects
[i
].h
;
2143 for ( ; i
< num_rects
; ++i
)
2144 rects
[i
].was_packed
= 0;
2148 //////////////////////////////////////////////////////////////////////////////
2152 // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
2153 // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
2155 STBTT_DEF
int stbtt_PackBegin(stbtt_pack_context
*spc
, unsigned char *pixels
, int pw
, int ph
, int stride_in_bytes
, int padding
, void *alloc_context
)
2157 stbrp_context
*context
= (stbrp_context
*) STBTT_malloc(sizeof(*context
) ,alloc_context
);
2158 int num_nodes
= pw
- padding
;
2159 stbrp_node
*nodes
= (stbrp_node
*) STBTT_malloc(sizeof(*nodes
) * num_nodes
,alloc_context
);
2161 if (context
== NULL
|| nodes
== NULL
) {
2162 if (context
!= NULL
) STBTT_free(context
, alloc_context
);
2163 if (nodes
!= NULL
) STBTT_free(nodes
, alloc_context
);
2167 spc
->user_allocator_context
= alloc_context
;
2170 spc
->pixels
= pixels
;
2171 spc
->pack_info
= context
;
2173 spc
->padding
= padding
;
2174 spc
->stride_in_bytes
= stride_in_bytes
!= 0 ? stride_in_bytes
: pw
;
2175 spc
->h_oversample
= 1;
2176 spc
->v_oversample
= 1;
2178 stbrp_init_target(context
, pw
-padding
, ph
-padding
, nodes
, num_nodes
);
2180 STBTT_memset(pixels
, 0, pw
*ph
); // background of 0 around pixels
2185 STBTT_DEF
void stbtt_PackEnd (stbtt_pack_context
*spc
)
2187 STBTT_free(spc
->nodes
, spc
->user_allocator_context
);
2188 STBTT_free(spc
->pack_info
, spc
->user_allocator_context
);
2191 STBTT_DEF
void stbtt_PackSetOversampling(stbtt_pack_context
*spc
, unsigned int h_oversample
, unsigned int v_oversample
)
2193 STBTT_assert(h_oversample
<= STBTT_MAX_OVERSAMPLE
);
2194 STBTT_assert(v_oversample
<= STBTT_MAX_OVERSAMPLE
);
2195 if (h_oversample
<= STBTT_MAX_OVERSAMPLE
)
2196 spc
->h_oversample
= h_oversample
;
2197 if (v_oversample
<= STBTT_MAX_OVERSAMPLE
)
2198 spc
->v_oversample
= v_oversample
;
2201 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
2203 static void stbtt__h_prefilter(unsigned char *pixels
, int w
, int h
, int stride_in_bytes
, unsigned int kernel_width
)
2205 unsigned char buffer
[STBTT_MAX_OVERSAMPLE
];
2206 int safe_w
= w
- kernel_width
;
2208 for (j
=0; j
< h
; ++j
) {
2211 STBTT_memset(buffer
, 0, kernel_width
);
2215 // make kernel_width a constant in common cases so compiler can optimize out the divide
2216 switch (kernel_width
) {
2218 for (i
=0; i
<= safe_w
; ++i
) {
2219 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2220 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2221 pixels
[i
] = (unsigned char) (total
/ 2);
2225 for (i
=0; i
<= safe_w
; ++i
) {
2226 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2227 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2228 pixels
[i
] = (unsigned char) (total
/ 3);
2232 for (i
=0; i
<= safe_w
; ++i
) {
2233 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2234 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2235 pixels
[i
] = (unsigned char) (total
/ 4);
2239 for (i
=0; i
<= safe_w
; ++i
) {
2240 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2241 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2242 pixels
[i
] = (unsigned char) (total
/ kernel_width
);
2247 for (; i
< w
; ++i
) {
2248 STBTT_assert(pixels
[i
] == 0);
2249 total
-= buffer
[i
& STBTT__OVER_MASK
];
2250 pixels
[i
] = (unsigned char) (total
/ kernel_width
);
2253 pixels
+= stride_in_bytes
;
2257 static void stbtt__v_prefilter(unsigned char *pixels
, int w
, int h
, int stride_in_bytes
, unsigned int kernel_width
)
2259 unsigned char buffer
[STBTT_MAX_OVERSAMPLE
];
2260 int safe_h
= h
- kernel_width
;
2262 for (j
=0; j
< w
; ++j
) {
2265 STBTT_memset(buffer
, 0, kernel_width
);
2269 // make kernel_width a constant in common cases so compiler can optimize out the divide
2270 switch (kernel_width
) {
2272 for (i
=0; i
<= safe_h
; ++i
) {
2273 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2274 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2275 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ 2);
2279 for (i
=0; i
<= safe_h
; ++i
) {
2280 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2281 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2282 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ 3);
2286 for (i
=0; i
<= safe_h
; ++i
) {
2287 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2288 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2289 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ 4);
2293 for (i
=0; i
<= safe_h
; ++i
) {
2294 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2295 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2296 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ kernel_width
);
2301 for (; i
< h
; ++i
) {
2302 STBTT_assert(pixels
[i
*stride_in_bytes
] == 0);
2303 total
-= buffer
[i
& STBTT__OVER_MASK
];
2304 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ kernel_width
);
2311 static float stbtt__oversample_shift(int oversample
)
2316 // The prefilter is a box filter of width "oversample",
2317 // which shifts phase by (oversample - 1)/2 pixels in
2318 // oversampled space. We want to shift in the opposite
2319 // direction to counter this.
2320 return (float)-(oversample
- 1) / (2.0f
* (float)oversample
);
2323 STBTT_DEF
int stbtt_PackFontRanges(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, stbtt_pack_range
*ranges
, int num_ranges
)
2325 stbtt_fontinfo info
;
2326 float recip_h
= 1.0f
/ spc
->h_oversample
;
2327 float recip_v
= 1.0f
/ spc
->v_oversample
;
2328 float sub_x
= stbtt__oversample_shift(spc
->h_oversample
);
2329 float sub_y
= stbtt__oversample_shift(spc
->v_oversample
);
2330 int i
,j
,k
,n
, return_value
= 1;
2331 stbrp_context
*context
= (stbrp_context
*) spc
->pack_info
;
2334 // flag all characters as NOT packed
2335 for (i
=0; i
< num_ranges
; ++i
)
2336 for (j
=0; j
< ranges
[i
].num_chars_in_range
; ++j
)
2337 ranges
[i
].chardata_for_range
[j
].x0
=
2338 ranges
[i
].chardata_for_range
[j
].y0
=
2339 ranges
[i
].chardata_for_range
[j
].x1
=
2340 ranges
[i
].chardata_for_range
[j
].y1
= 0;
2343 for (i
=0; i
< num_ranges
; ++i
)
2344 n
+= ranges
[i
].num_chars_in_range
;
2346 rects
= (stbrp_rect
*) STBTT_malloc(sizeof(*rects
) * n
, spc
->user_allocator_context
);
2350 stbtt_InitFont(&info
, fontdata
, stbtt_GetFontOffsetForIndex(fontdata
,font_index
));
2352 for (i
=0; i
< num_ranges
; ++i
) {
2353 float fh
= ranges
[i
].font_size
;
2354 float scale
= fh
> 0 ? stbtt_ScaleForPixelHeight(&info
, fh
) : stbtt_ScaleForMappingEmToPixels(&info
, -fh
);
2355 for (j
=0; j
< ranges
[i
].num_chars_in_range
; ++j
) {
2357 stbtt_GetCodepointBitmapBoxSubpixel(&info
, ranges
[i
].first_unicode_char_in_range
+ j
,
2358 scale
* spc
->h_oversample
,
2359 scale
* spc
->v_oversample
,
2362 rects
[k
].w
= (stbrp_coord
) (x1
-x0
+ spc
->padding
+ spc
->h_oversample
-1);
2363 rects
[k
].h
= (stbrp_coord
) (y1
-y0
+ spc
->padding
+ spc
->v_oversample
-1);
2368 stbrp_pack_rects(context
, rects
, k
);
2371 for (i
=0; i
< num_ranges
; ++i
) {
2372 float fh
= ranges
[i
].font_size
;
2373 float scale
= fh
> 0 ? stbtt_ScaleForPixelHeight(&info
, fh
) : stbtt_ScaleForMappingEmToPixels(&info
, -fh
);
2374 for (j
=0; j
< ranges
[i
].num_chars_in_range
; ++j
) {
2375 stbrp_rect
*r
= &rects
[k
];
2376 if (r
->was_packed
) {
2377 stbtt_packedchar
*bc
= &ranges
[i
].chardata_for_range
[j
];
2378 int advance
, lsb
, x0
,y0
,x1
,y1
;
2379 int glyph
= stbtt_FindGlyphIndex(&info
, ranges
[i
].first_unicode_char_in_range
+ j
);
2380 stbrp_coord pad
= (stbrp_coord
) spc
->padding
;
2382 // pad on left and top
2387 stbtt_GetGlyphHMetrics(&info
, glyph
, &advance
, &lsb
);
2388 stbtt_GetGlyphBitmapBox(&info
, glyph
,
2389 scale
* spc
->h_oversample
,
2390 scale
* spc
->v_oversample
,
2392 stbtt_MakeGlyphBitmapSubpixel(&info
,
2393 spc
->pixels
+ r
->x
+ r
->y
*spc
->stride_in_bytes
,
2394 r
->w
- spc
->h_oversample
+1,
2395 r
->h
- spc
->v_oversample
+1,
2396 spc
->stride_in_bytes
,
2397 scale
* spc
->h_oversample
,
2398 scale
* spc
->v_oversample
,
2402 if (spc
->h_oversample
> 1)
2403 stbtt__h_prefilter(spc
->pixels
+ r
->x
+ r
->y
*spc
->stride_in_bytes
,
2404 r
->w
, r
->h
, spc
->stride_in_bytes
,
2407 if (spc
->v_oversample
> 1)
2408 stbtt__v_prefilter(spc
->pixels
+ r
->x
+ r
->y
*spc
->stride_in_bytes
,
2409 r
->w
, r
->h
, spc
->stride_in_bytes
,
2412 bc
->x0
= (stbtt_int16
) r
->x
;
2413 bc
->y0
= (stbtt_int16
) r
->y
;
2414 bc
->x1
= (stbtt_int16
) (r
->x
+ r
->w
);
2415 bc
->y1
= (stbtt_int16
) (r
->y
+ r
->h
);
2416 bc
->xadvance
= scale
* advance
;
2417 bc
->xoff
= (float) x0
* recip_h
+ sub_x
;
2418 bc
->yoff
= (float) y0
* recip_v
+ sub_y
;
2419 bc
->xoff2
= (x0
+ r
->w
) * recip_h
+ sub_x
;
2420 bc
->yoff2
= (y0
+ r
->h
) * recip_v
+ sub_y
;
2422 return_value
= 0; // if any fail, report failure
2429 STBTT_free(rects
, spc
->user_allocator_context
);
2430 return return_value
;
2433 STBTT_DEF
int stbtt_PackFontRange(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, float font_size
,
2434 int first_unicode_char_in_range
, int num_chars_in_range
, stbtt_packedchar
*chardata_for_range
)
2436 stbtt_pack_range range
;
2437 range
.first_unicode_char_in_range
= first_unicode_char_in_range
;
2438 range
.num_chars_in_range
= num_chars_in_range
;
2439 range
.chardata_for_range
= chardata_for_range
;
2440 range
.font_size
= font_size
;
2441 return stbtt_PackFontRanges(spc
, fontdata
, font_index
, &range
, 1);
2444 STBTT_DEF
void stbtt_GetPackedQuad(stbtt_packedchar
*chardata
, int pw
, int ph
, int char_index
, float *xpos
, float *ypos
, stbtt_aligned_quad
*q
, int align_to_integer
)
2446 float ipw
= 1.0f
/ pw
, iph
= 1.0f
/ ph
;
2447 stbtt_packedchar
*b
= chardata
+ char_index
;
2449 if (align_to_integer
) {
2450 float x
= (float) STBTT_ifloor((*xpos
+ b
->xoff
) + 0.5f
);
2451 float y
= (float) STBTT_ifloor((*ypos
+ b
->yoff
) + 0.5f
);
2454 q
->x1
= x
+ b
->xoff2
- b
->xoff
;
2455 q
->y1
= y
+ b
->yoff2
- b
->yoff
;
2457 q
->x0
= *xpos
+ b
->xoff
;
2458 q
->y0
= *ypos
+ b
->yoff
;
2459 q
->x1
= *xpos
+ b
->xoff2
;
2460 q
->y1
= *ypos
+ b
->yoff2
;
2463 q
->s0
= b
->x0
* ipw
;
2464 q
->t0
= b
->y0
* iph
;
2465 q
->s1
= b
->x1
* ipw
;
2466 q
->t1
= b
->y1
* iph
;
2468 *xpos
+= b
->xadvance
;
2472 //////////////////////////////////////////////////////////////////////////////
2474 // font name matching -- recommended not to use this
2477 // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
2478 static stbtt_int32
stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8
*s1
, stbtt_int32 len1
, const stbtt_uint8
*s2
, stbtt_int32 len2
)
2482 // convert utf16 to utf8 and compare the results while converting
2484 stbtt_uint16 ch
= s2
[0]*256 + s2
[1];
2486 if (i
>= len1
) return -1;
2487 if (s1
[i
++] != ch
) return -1;
2488 } else if (ch
< 0x800) {
2489 if (i
+1 >= len1
) return -1;
2490 if (s1
[i
++] != 0xc0 + (ch
>> 6)) return -1;
2491 if (s1
[i
++] != 0x80 + (ch
& 0x3f)) return -1;
2492 } else if (ch
>= 0xd800 && ch
< 0xdc00) {
2494 stbtt_uint16 ch2
= s2
[2]*256 + s2
[3];
2495 if (i
+3 >= len1
) return -1;
2496 c
= ((ch
- 0xd800) << 10) + (ch2
- 0xdc00) + 0x10000;
2497 if (s1
[i
++] != 0xf0 + (c
>> 18)) return -1;
2498 if (s1
[i
++] != 0x80 + ((c
>> 12) & 0x3f)) return -1;
2499 if (s1
[i
++] != 0x80 + ((c
>> 6) & 0x3f)) return -1;
2500 if (s1
[i
++] != 0x80 + ((c
) & 0x3f)) return -1;
2501 s2
+= 2; // plus another 2 below
2503 } else if (ch
>= 0xdc00 && ch
< 0xe000) {
2506 if (i
+2 >= len1
) return -1;
2507 if (s1
[i
++] != 0xe0 + (ch
>> 12)) return -1;
2508 if (s1
[i
++] != 0x80 + ((ch
>> 6) & 0x3f)) return -1;
2509 if (s1
[i
++] != 0x80 + ((ch
) & 0x3f)) return -1;
2517 STBTT_DEF
int stbtt_CompareUTF8toUTF16_bigendian(const char *s1
, int len1
, const char *s2
, int len2
)
2519 return len1
== stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8
*) s1
, len1
, (const stbtt_uint8
*) s2
, len2
);
2522 // returns results in whatever encoding you request... but note that 2-byte encodings
2523 // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
2524 STBTT_DEF
const char *stbtt_GetFontNameString(const stbtt_fontinfo
*font
, int *length
, int platformID
, int encodingID
, int languageID
, int nameID
)
2526 stbtt_int32 i
,count
,stringOffset
;
2527 stbtt_uint8
*fc
= font
->data
;
2528 stbtt_uint32 offset
= font
->fontstart
;
2529 stbtt_uint32 nm
= stbtt__find_table(fc
, offset
, "name");
2530 if (!nm
) return NULL
;
2532 count
= ttUSHORT(fc
+nm
+2);
2533 stringOffset
= nm
+ ttUSHORT(fc
+nm
+4);
2534 for (i
=0; i
< count
; ++i
) {
2535 stbtt_uint32 loc
= nm
+ 6 + 12 * i
;
2536 if (platformID
== ttUSHORT(fc
+loc
+0) && encodingID
== ttUSHORT(fc
+loc
+2)
2537 && languageID
== ttUSHORT(fc
+loc
+4) && nameID
== ttUSHORT(fc
+loc
+6)) {
2538 *length
= ttUSHORT(fc
+loc
+8);
2539 return (const char *) (fc
+stringOffset
+ttUSHORT(fc
+loc
+10));
2545 static int stbtt__matchpair(stbtt_uint8
*fc
, stbtt_uint32 nm
, stbtt_uint8
*name
, stbtt_int32 nlen
, stbtt_int32 target_id
, stbtt_int32 next_id
)
2548 stbtt_int32 count
= ttUSHORT(fc
+nm
+2);
2549 stbtt_int32 stringOffset
= nm
+ ttUSHORT(fc
+nm
+4);
2551 for (i
=0; i
< count
; ++i
) {
2552 stbtt_uint32 loc
= nm
+ 6 + 12 * i
;
2553 stbtt_int32 id
= ttUSHORT(fc
+loc
+6);
2554 if (id
== target_id
) {
2555 // find the encoding
2556 stbtt_int32 platform
= ttUSHORT(fc
+loc
+0), encoding
= ttUSHORT(fc
+loc
+2), language
= ttUSHORT(fc
+loc
+4);
2558 // is this a Unicode encoding?
2559 if (platform
== 0 || (platform
== 3 && encoding
== 1) || (platform
== 3 && encoding
== 10)) {
2560 stbtt_int32 slen
= ttUSHORT(fc
+loc
+8);
2561 stbtt_int32 off
= ttUSHORT(fc
+loc
+10);
2563 // check if there's a prefix match
2564 stbtt_int32 matchlen
= stbtt__CompareUTF8toUTF16_bigendian_prefix(name
, nlen
, fc
+stringOffset
+off
,slen
);
2565 if (matchlen
>= 0) {
2566 // check for target_id+1 immediately following, with same encoding & language
2567 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
) {
2568 slen
= ttUSHORT(fc
+loc
+12+8);
2569 off
= ttUSHORT(fc
+loc
+12+10);
2571 if (matchlen
== nlen
)
2573 } else if (matchlen
< nlen
&& name
[matchlen
] == ' ') {
2575 if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name
+matchlen
), nlen
-matchlen
, (char*)(fc
+stringOffset
+off
),slen
))
2579 // if nothing immediately following
2580 if (matchlen
== nlen
)
2586 // @TODO handle other encodings
2592 static int stbtt__matches(stbtt_uint8
*fc
, stbtt_uint32 offset
, stbtt_uint8
*name
, stbtt_int32 flags
)
2594 stbtt_int32 nlen
= (stbtt_int32
) STBTT_strlen((char *) name
);
2596 if (!stbtt__isfont(fc
+offset
)) return 0;
2598 // check italics/bold/underline flags in macStyle...
2600 hd
= stbtt__find_table(fc
, offset
, "head");
2601 if ((ttUSHORT(fc
+hd
+44) & 7) != (flags
& 7)) return 0;
2604 nm
= stbtt__find_table(fc
, offset
, "name");
2608 // if we checked the macStyle flags, then just check the family and ignore the subfamily
2609 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 16, -1)) return 1;
2610 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 1, -1)) return 1;
2611 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 3, -1)) return 1;
2613 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 16, 17)) return 1;
2614 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 1, 2)) return 1;
2615 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 3, -1)) return 1;
2621 STBTT_DEF
int stbtt_FindMatchingFont(const unsigned char *font_collection
, const char *name_utf8
, stbtt_int32 flags
)
2625 stbtt_int32 off
= stbtt_GetFontOffsetForIndex(font_collection
, i
);
2626 if (off
< 0) return off
;
2627 if (stbtt__matches((stbtt_uint8
*) font_collection
, off
, (stbtt_uint8
*) name_utf8
, flags
))
2632 #endif // STB_TRUETYPE_IMPLEMENTATION