1 // stb_truetype.h - v1.09 - public domain
2 // authored from 2009-2015 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
53 // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
54 // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
55 // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
56 // variant PackFontRanges to pack and render in separate phases;
57 // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
58 // fixed an assert() bug in the new rasterizer
59 // replace assert() with STBTT_assert() in new rasterizer
60 // 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
61 // also more precise AA rasterizer, except if shapes overlap
62 // remove need for STBTT_sort
63 // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
64 // 1.04 (2015-04-15) typo in example
65 // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
67 // Full history can be found at the end of this file.
71 // This software is in the public domain. Where that dedication is not
72 // recognized, you are granted a perpetual, irrevocable license to copy,
73 // distribute, and modify this file as you see fit.
77 // Include this file in whatever places neeed to refer to it. In ONE C/C++
79 // #define STB_TRUETYPE_IMPLEMENTATION
80 // before the #include of this file. This expands out the actual
81 // implementation into that C/C++ file.
83 // To make the implementation private to the file that generates the implementation,
84 // #define STBTT_STATIC
86 // Simple 3D API (don't ship this, but it's fine for tools and quick start)
87 // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
88 // stbtt_GetBakedQuad() -- compute quad to draw for a given char
90 // Improved 3D API (more shippable):
91 // #include "stb_rect_pack.h" -- optional, but you really want it
93 // stbtt_PackSetOversample() -- for improved quality on small fonts
94 // stbtt_PackFontRanges() -- pack and renders
96 // stbtt_GetPackedQuad()
98 // "Load" a font file from a memory buffer (you have to keep the buffer loaded)
100 // stbtt_GetFontOffsetForIndex() -- use for TTC font collections
102 // Render a unicode codepoint to a bitmap
103 // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
104 // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
105 // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
107 // Character advance/positioning
108 // stbtt_GetCodepointHMetrics()
109 // stbtt_GetFontVMetrics()
110 // stbtt_GetCodepointKernAdvance()
112 // Starting with version 1.06, the rasterizer was replaced with a new,
113 // faster and generally-more-precise rasterizer. The new rasterizer more
114 // accurately measures pixel coverage for anti-aliasing, except in the case
115 // where multiple shapes overlap, in which case it overestimates the AA pixel
116 // coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
117 // this turns out to be a problem, you can re-enable the old rasterizer with
118 // #define STBTT_RASTERIZER_VERSION 1
119 // which will incur about a 15% speed hit.
121 // ADDITIONAL DOCUMENTATION
123 // Immediately after this block comment are a series of sample programs.
125 // After the sample programs is the "header file" section. This section
126 // includes documentation for each API function.
128 // Some important concepts to understand to use this library:
131 // Characters are defined by unicode codepoints, e.g. 65 is
132 // uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
133 // the hiragana for "ma".
136 // A visual character shape (every codepoint is rendered as
140 // A font-specific integer ID representing a glyph
143 // Glyph shapes are defined relative to a baseline, which is the
144 // bottom of uppercase characters. Characters extend both above
145 // and below the baseline.
148 // As you draw text to the screen, you keep track of a "current point"
149 // which is the origin of each character. The current point's vertical
150 // position is the baseline. Even "baked fonts" use this model.
152 // Vertical Font Metrics
153 // The vertical qualities of the font, used to vertically position
154 // and space the characters. See docs for stbtt_GetFontVMetrics.
156 // Font Size in Pixels or Points
157 // The preferred interface for specifying font sizes in stb_truetype
158 // is to specify how tall the font's vertical extent should be in pixels.
159 // If that sounds good enough, skip the next paragraph.
161 // Most font APIs instead use "points", which are a common typographic
162 // measurement for describing font size, defined as 72 points per inch.
163 // stb_truetype provides a point API for compatibility. However, true
164 // "per inch" conventions don't make much sense on computer displays
165 // since they different monitors have different number of pixels per
166 // inch. For example, Windows traditionally uses a convention that
167 // there are 96 pixels per inch, thus making 'inch' measurements have
168 // nothing to do with inches, and thus effectively defining a point to
169 // be 1.333 pixels. Additionally, the TrueType font data provides
170 // an explicit scale factor to scale a given font's glyphs to points,
171 // but the author has observed that this scale factor is often wrong
172 // for non-commercial fonts, thus making fonts scaled in points
173 // according to the TrueType spec incoherently sized in practice.
179 // - Use the functions with Subpixel at the end to allow your characters
180 // to have subpixel positioning. Since the font is anti-aliased, not
181 // hinted, this is very import for quality. (This is not possible with
184 // - Kerning is now supported, and if you're supporting subpixel rendering
185 // then kerning is worth using to give your text a polished look.
189 // - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
190 // if you don't do this, stb_truetype is forced to do the conversion on
193 // - There are a lot of memory allocations. We should modify it to take
194 // a temp buffer and allocate from the temp buffer (without freeing),
195 // should help performance a lot.
199 // The system uses the raw data found in the .ttf file without changing it
200 // and without building auxiliary data structures. This is a bit inefficient
201 // on little-endian systems (the data is big-endian), but assuming you're
202 // caching the bitmaps or glyph shapes this shouldn't be a big deal.
204 // It appears to be very hard to programmatically determine what font a
205 // given file is in a general way. I provide an API for this, but I don't
209 // SOURCE STATISTICS (based on v0.6c, 2050 LOC)
211 // Documentation & header file 520 LOC \___ 660 LOC documentation
212 // Sample code 140 LOC /
213 // Truetype parsing 620 LOC ---- 620 LOC TrueType
214 // Software rasterization 240 LOC \ .
215 // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
216 // Bitmap management 100 LOC /
217 // Baked bitmap interface 70 LOC /
218 // Font name matching & access 150 LOC ---- 150
219 // C runtime library abstraction 60 LOC ---- 60
222 // PERFORMANCE MEASUREMENTS FOR 1.06:
225 // Previous release: 8.83 s 7.68 s
226 // Pool allocations: 7.72 s 6.34 s
227 // Inline sort : 6.54 s 5.65 s
228 // New rasterizer : 5.63 s 5.00 s
230 //////////////////////////////////////////////////////////////////////////////
231 //////////////////////////////////////////////////////////////////////////////
236 // Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
239 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
240 #include "stb_truetype.h"
242 unsigned char ttf_buffer
[1<<20];
243 unsigned char temp_bitmap
[512*512];
245 stbtt_bakedchar cdata
[96]; // ASCII 32..126 is 95 glyphs
248 void my_stbtt_initfont(void)
250 fread(ttf_buffer
, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
251 stbtt_BakeFontBitmap(ttf_buffer
,0, 32.0, temp_bitmap
,512,512, 32,96, cdata
); // no guarantee this fits!
252 // can free ttf_buffer at this point
253 glGenTextures(1, &ftex
);
254 glBindTexture(GL_TEXTURE_2D
, ftex
);
255 glTexImage2D(GL_TEXTURE_2D
, 0, GL_ALPHA
, 512,512, 0, GL_ALPHA
, GL_UNSIGNED_BYTE
, temp_bitmap
);
256 // can free temp_bitmap at this point
257 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
260 void my_stbtt_print(float x
, float y
, char *text
)
262 // assume orthographic projection with units = screen pixels, origin at top left
263 glEnable(GL_TEXTURE_2D
);
264 glBindTexture(GL_TEXTURE_2D
, ftex
);
267 if (*text
>= 32 && *text
< 128) {
268 stbtt_aligned_quad q
;
269 stbtt_GetBakedQuad(cdata
, 512,512, *text
-32, &x
,&y
,&q
,1);//1=opengl & d3d10+,0=d3d9
270 glTexCoord2f(q
.s0
,q
.t1
); glVertex2f(q
.x0
,q
.y0
);
271 glTexCoord2f(q
.s1
,q
.t1
); glVertex2f(q
.x1
,q
.y0
);
272 glTexCoord2f(q
.s1
,q
.t0
); glVertex2f(q
.x1
,q
.y1
);
273 glTexCoord2f(q
.s0
,q
.t0
); glVertex2f(q
.x0
,q
.y1
);
282 //////////////////////////////////////////////////////////////////////////////
284 // Complete program (this compiles): get a single bitmap, print as ASCII art
288 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
289 #include "stb_truetype.h"
291 char ttf_buffer
[1<<25];
293 int main(int argc
, char **argv
)
296 unsigned char *bitmap
;
297 int w
,h
,i
,j
,c
= (argc
> 1 ? atoi(argv
[1]) : 'a'), s
= (argc
> 2 ? atoi(argv
[2]) : 20);
299 fread(ttf_buffer
, 1, 1<<25, fopen(argc
> 3 ? argv
[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
301 stbtt_InitFont(&font
, ttf_buffer
, stbtt_GetFontOffsetForIndex(ttf_buffer
,0));
302 bitmap
= stbtt_GetCodepointBitmap(&font
, 0,stbtt_ScaleForPixelHeight(&font
, s
), c
, &w
, &h
, 0,0);
304 for (j
=0; j
< h
; ++j
) {
305 for (i
=0; i
< w
; ++i
)
306 putchar(" .:ioVM@"[bitmap
[j
*w
+i
]>>5]);
326 //////////////////////////////////////////////////////////////////////////////
328 // Complete program: print "Hello World!" banner, with bugs
332 unsigned char screen
[20][79];
334 int main(int arg
, char **argv
)
337 int i
,j
,ascent
,baseline
,ch
=0;
338 float scale
, xpos
=2; // leave a little padding in case the character extends left
339 char *text
= "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
341 fread(buffer
, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
342 stbtt_InitFont(&font
, buffer
, 0);
344 scale
= stbtt_ScaleForPixelHeight(&font
, 15);
345 stbtt_GetFontVMetrics(&font
, &ascent
,0,0);
346 baseline
= (int) (ascent
*scale
);
349 int advance
,lsb
,x0
,y0
,x1
,y1
;
350 float x_shift
= xpos
- (float) floor(xpos
);
351 stbtt_GetCodepointHMetrics(&font
, text
[ch
], &advance
, &lsb
);
352 stbtt_GetCodepointBitmapBoxSubpixel(&font
, text
[ch
], scale
,scale
,x_shift
,0, &x0
,&y0
,&x1
,&y1
);
353 stbtt_MakeCodepointBitmapSubpixel(&font
, &screen
[baseline
+ y0
][(int) xpos
+ x0
], x1
-x0
,y1
-y0
, 79, scale
,scale
,x_shift
,0, text
[ch
]);
354 // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
355 // because this API is really for baking character bitmaps into textures. if you want to render
356 // a sequence of characters, you really need to render each bitmap to a temp buffer, then
357 // "alpha blend" that into the working buffer
358 xpos
+= (advance
* scale
);
360 xpos
+= scale
*stbtt_GetCodepointKernAdvance(&font
, text
[ch
],text
[ch
+1]);
364 for (j
=0; j
< 20; ++j
) {
365 for (i
=0; i
< 78; ++i
)
366 putchar(" .:ioVM@"[screen
[j
][i
]>>5]);
375 //////////////////////////////////////////////////////////////////////////////
376 //////////////////////////////////////////////////////////////////////////////
378 //// INTEGRATION WITH YOUR CODEBASE
380 //// The following sections allow you to supply alternate definitions
381 //// of C library functions used by stb_truetype.
383 #ifdef STB_TRUETYPE_IMPLEMENTATION
384 // #define your own (u)stbtt_int8/16/32 before including to override this
386 typedef unsigned char stbtt_uint8
;
387 typedef signed char stbtt_int8
;
388 typedef unsigned short stbtt_uint16
;
389 typedef signed short stbtt_int16
;
390 typedef unsigned int stbtt_uint32
;
391 typedef signed int stbtt_int32
;
394 typedef char stbtt__check_size32
[sizeof(stbtt_int32
)==4 ? 1 : -1];
395 typedef char stbtt__check_size16
[sizeof(stbtt_int16
)==2 ? 1 : -1];
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
;
514 typedef struct stbtt_fontinfo stbtt_fontinfo
;
515 #ifndef STB_RECT_PACK_VERSION
516 typedef struct stbrp_rect stbrp_rect
;
519 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
);
520 // Initializes a packing context stored in the passed-in stbtt_pack_context.
521 // Future calls using this context will pack characters into the bitmap passed
522 // in here: a 1-channel bitmap that is weight x height. stride_in_bytes is
523 // the distance from one row to the next (or 0 to mean they are packed tightly
524 // together). "padding" is the amount of padding to leave between each
525 // character (normally you want '1' for bitmaps you'll use as textures with
526 // bilinear filtering).
528 // Returns 0 on failure, 1 on success.
530 STBTT_DEF
void stbtt_PackEnd (stbtt_pack_context
*spc
);
531 // Cleans up the packing context and frees all memory.
533 #define STBTT_POINT_SIZE(x) (-(x))
535 STBTT_DEF
int stbtt_PackFontRange(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, float font_size
,
536 int first_unicode_char_in_range
, int num_chars_in_range
, stbtt_packedchar
*chardata_for_range
);
537 // Creates character bitmaps from the font_index'th font found in fontdata (use
538 // font_index=0 if you don't know what that is). It creates num_chars_in_range
539 // bitmaps for characters with unicode values starting at first_unicode_char_in_range
540 // and increasing. Data for how to render them is stored in chardata_for_range;
541 // pass these to stbtt_GetPackedQuad to get back renderable quads.
543 // font_size is the full height of the character from ascender to descender,
544 // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
545 // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
546 // and pass that result as 'font_size':
547 // ..., 20 , ... // font max minus min y is 20 pixels tall
548 // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
553 int first_unicode_codepoint_in_range
; // if non-zero, then the chars are continuous, and this is the first codepoint
554 int *array_of_unicode_codepoints
; // if non-zero, then this is an array of unicode codepoints
556 stbtt_packedchar
*chardata_for_range
; // output
557 unsigned char h_oversample
, v_oversample
; // don't set these, they're used internally
560 STBTT_DEF
int stbtt_PackFontRanges(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, stbtt_pack_range
*ranges
, int num_ranges
);
561 // Creates character bitmaps from multiple ranges of characters stored in
562 // ranges. This will usually create a better-packed bitmap than multiple
563 // calls to stbtt_PackFontRange. Note that you can call this multiple
564 // times within a single PackBegin/PackEnd.
566 STBTT_DEF
void stbtt_PackSetOversampling(stbtt_pack_context
*spc
, unsigned int h_oversample
, unsigned int v_oversample
);
567 // Oversampling a font increases the quality by allowing higher-quality subpixel
568 // positioning, and is especially valuable at smaller text sizes.
570 // This function sets the amount of oversampling for all following calls to
571 // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
572 // pack context. The default (no oversampling) is achieved by h_oversample=1
573 // and v_oversample=1. The total number of pixels required is
574 // h_oversample*v_oversample larger than the default; for example, 2x2
575 // oversampling requires 4x the storage of 1x1. For best results, render
576 // oversampled textures with bilinear filtering. Look at the readme in
577 // stb/tests/oversample for information about oversampled fonts
579 // To use with PackFontRangesGather etc., you must set it before calls
580 // call to PackFontRangesGatherRects.
582 STBTT_DEF
void stbtt_GetPackedQuad(stbtt_packedchar
*chardata
, int pw
, int ph
, // same data as above
583 int char_index
, // character to display
584 float *xpos
, float *ypos
, // pointers to current position in screen pixel space
585 stbtt_aligned_quad
*q
, // output: quad to draw
586 int align_to_integer
);
588 STBTT_DEF
int stbtt_PackFontRangesGatherRects(stbtt_pack_context
*spc
, stbtt_fontinfo
*info
, stbtt_pack_range
*ranges
, int num_ranges
, stbrp_rect
*rects
);
589 STBTT_DEF
void stbtt_PackFontRangesPackRects(stbtt_pack_context
*spc
, stbrp_rect
*rects
, int num_rects
);
590 STBTT_DEF
int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context
*spc
, stbtt_fontinfo
*info
, stbtt_pack_range
*ranges
, int num_ranges
, stbrp_rect
*rects
);
591 // Calling these functions in sequence is roughly equivalent to calling
592 // stbtt_PackFontRanges(). If you more control over the packing of multiple
593 // fonts, or if you want to pack custom data into a font texture, take a look
594 // at the source to of stbtt_PackFontRanges() and create a custom version
595 // using these functions, e.g. call GatherRects multiple times,
596 // building up a single array of rects, then call PackRects once,
597 // then call RenderIntoRects repeatedly. This may result in a
598 // better packing than calling PackFontRanges multiple times
601 // this is an opaque structure that you shouldn't mess with which holds
602 // all the context needed from PackBegin to PackEnd.
603 struct stbtt_pack_context
{
604 void *user_allocator_context
;
610 unsigned int h_oversample
, v_oversample
;
611 unsigned char *pixels
;
615 //////////////////////////////////////////////////////////////////////////////
621 STBTT_DEF
int stbtt_GetFontOffsetForIndex(const unsigned char *data
, int index
);
622 // Each .ttf/.ttc file may have more than one font. Each font has a sequential
623 // index number starting from 0. Call this function to get the font offset for
624 // a given index; it returns -1 if the index is out of range. A regular .ttf
625 // file will only define one font and it always be at offset 0, so it will
626 // return '0' for index 0, and -1 for all other indices. You can just skip
627 // this step if you know it's that kind of font.
630 // The following structure is defined publically so you can declare one on
631 // the stack or as a global or etc, but you should treat it as opaque.
632 typedef struct stbtt_fontinfo
635 unsigned char * data
; // pointer to .ttf file
636 int fontstart
; // offset of start of font
638 int numGlyphs
; // number of glyphs, needed for range checking
640 int loca
,head
,glyf
,hhea
,hmtx
,kern
; // table locations as offset from start of .ttf
641 int index_map
; // a cmap mapping for our chosen character encoding
642 int indexToLocFormat
; // format needed to map from glyph index to glyph
645 STBTT_DEF
int stbtt_InitFont(stbtt_fontinfo
*info
, const unsigned char *data
, int offset
);
646 // Given an offset into the file that defines a font, this function builds
647 // the necessary cached info for the rest of the system. You must allocate
648 // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
649 // need to do anything special to free it, because the contents are pure
650 // value data with no additional data structures. Returns 0 on failure.
653 //////////////////////////////////////////////////////////////////////////////
655 // CHARACTER TO GLYPH-INDEX CONVERSIOn
657 STBTT_DEF
int stbtt_FindGlyphIndex(const stbtt_fontinfo
*info
, int unicode_codepoint
);
658 // If you're going to perform multiple operations on the same character
659 // and you want a speed-up, call this function with the character you're
660 // going to process, then use glyph-based functions instead of the
661 // codepoint-based functions.
664 //////////////////////////////////////////////////////////////////////////////
666 // CHARACTER PROPERTIES
669 STBTT_DEF
float stbtt_ScaleForPixelHeight(const stbtt_fontinfo
*info
, float pixels
);
670 // computes a scale factor to produce a font whose "height" is 'pixels' tall.
671 // Height is measured as the distance from the highest ascender to the lowest
672 // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
674 // scale = pixels / (ascent - descent)
675 // so if you prefer to measure height by the ascent only, use a similar calculation.
677 STBTT_DEF
float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo
*info
, float pixels
);
678 // computes a scale factor to produce a font whose EM size is mapped to
679 // 'pixels' tall. This is probably what traditional APIs compute, but
682 STBTT_DEF
void stbtt_GetFontVMetrics(const stbtt_fontinfo
*info
, int *ascent
, int *descent
, int *lineGap
);
683 // ascent is the coordinate above the baseline the font extends; descent
684 // is the coordinate below the baseline the font extends (i.e. it is typically negative)
685 // lineGap is the spacing between one row's descent and the next row's ascent...
686 // so you should advance the vertical position by "*ascent - *descent + *lineGap"
687 // these are expressed in unscaled coordinates, so you must multiply by
688 // the scale factor for a given size
690 STBTT_DEF
void stbtt_GetFontBoundingBox(const stbtt_fontinfo
*info
, int *x0
, int *y0
, int *x1
, int *y1
);
691 // the bounding box around all possible characters
693 STBTT_DEF
void stbtt_GetCodepointHMetrics(const stbtt_fontinfo
*info
, int codepoint
, int *advanceWidth
, int *leftSideBearing
);
694 // leftSideBearing is the offset from the current horizontal position to the left edge of the character
695 // advanceWidth is the offset from the current horizontal position to the next horizontal position
696 // these are expressed in unscaled coordinates
698 STBTT_DEF
int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo
*info
, int ch1
, int ch2
);
699 // an additional amount to add to the 'advance' value between ch1 and ch2
701 STBTT_DEF
int stbtt_GetCodepointBox(const stbtt_fontinfo
*info
, int codepoint
, int *x0
, int *y0
, int *x1
, int *y1
);
702 // Gets the bounding box of the visible part of the glyph, in unscaled coordinates
704 STBTT_DEF
void stbtt_GetGlyphHMetrics(const stbtt_fontinfo
*info
, int glyph_index
, int *advanceWidth
, int *leftSideBearing
);
705 STBTT_DEF
int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo
*info
, int glyph1
, int glyph2
);
706 STBTT_DEF
int stbtt_GetGlyphBox(const stbtt_fontinfo
*info
, int glyph_index
, int *x0
, int *y0
, int *x1
, int *y1
);
707 // as above, but takes one or more glyph indices for greater efficiency
710 //////////////////////////////////////////////////////////////////////////////
712 // GLYPH SHAPES (you probably don't need these, but they have to go before
713 // the bitmaps for C declaration-order reasons)
716 #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
724 #ifndef stbtt_vertex // you can predefine this to use different values
725 // (we share this with other code at RAD)
726 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
729 stbtt_vertex_type x
,y
,cx
,cy
;
730 unsigned char type
,padding
;
734 STBTT_DEF
int stbtt_IsGlyphEmpty(const stbtt_fontinfo
*info
, int glyph_index
);
735 // returns non-zero if nothing is drawn for this glyph
737 STBTT_DEF
int stbtt_GetCodepointShape(const stbtt_fontinfo
*info
, int unicode_codepoint
, stbtt_vertex
**vertices
);
738 STBTT_DEF
int stbtt_GetGlyphShape(const stbtt_fontinfo
*info
, int glyph_index
, stbtt_vertex
**vertices
);
739 // returns # of vertices and fills *vertices with the pointer to them
740 // these are expressed in "unscaled" coordinates
742 // The shape is a series of countours. Each one starts with
743 // a STBTT_moveto, then consists of a series of mixed
744 // STBTT_lineto and STBTT_curveto segments. A lineto
745 // draws a line from previous endpoint to its x,y; a curveto
746 // draws a quadratic bezier from previous endpoint to
747 // its x,y, using cx,cy as the bezier control point.
749 STBTT_DEF
void stbtt_FreeShape(const stbtt_fontinfo
*info
, stbtt_vertex
*vertices
);
750 // frees the data allocated above
752 //////////////////////////////////////////////////////////////////////////////
757 STBTT_DEF
void stbtt_FreeBitmap(unsigned char *bitmap
, void *userdata
);
758 // frees the bitmap allocated below
760 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
);
761 // allocates a large-enough single-channel 8bpp bitmap and renders the
762 // specified character/glyph at the specified scale into it, with
763 // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
764 // *width & *height are filled out with the width & height of the bitmap,
765 // which is stored left-to-right, top-to-bottom.
767 // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
769 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
);
770 // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
771 // shift for the character
773 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
);
774 // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
775 // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
776 // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
777 // width and height and positioning info for it first.
779 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
);
780 // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
781 // shift for the character
783 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
);
784 // get the bbox of the bitmap centered around the glyph origin; so the
785 // bitmap width is ix1-ix0, height is iy1-iy0, and location to place
786 // the bitmap top left is (leftSideBearing*scale,iy0).
787 // (Note that the bitmap uses y-increases-down, but the shape uses
788 // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
790 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
);
791 // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
792 // shift for the character
794 // the following functions are equivalent to the above functions, but operate
795 // on glyph indices instead of Unicode codepoints (for efficiency)
796 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
);
797 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
);
798 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
);
799 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
);
800 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
);
801 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
);
804 // @TODO: don't expose this structure
808 unsigned char *pixels
;
811 // rasterize a shape with quadratic beziers into a bitmap
812 STBTT_DEF
void stbtt_Rasterize(stbtt__bitmap
*result
, // 1-channel bitmap to draw into
813 float flatness_in_pixels
, // allowable error of curve in pixels
814 stbtt_vertex
*vertices
, // array of vertices defining shape
815 int num_verts
, // number of vertices in above array
816 float scale_x
, float scale_y
, // scale applied to input vertices
817 float shift_x
, float shift_y
, // translation applied to input vertices
818 int x_off
, int y_off
, // another translation applied to input
819 int invert
, // if non-zero, vertically flip shape
820 void *userdata
); // context for to STBTT_MALLOC
822 //////////////////////////////////////////////////////////////////////////////
824 // Finding the right font...
826 // You should really just solve this offline, keep your own tables
827 // of what font is what, and don't try to get it out of the .ttf file.
828 // That's because getting it out of the .ttf file is really hard, because
829 // the names in the file can appear in many possible encodings, in many
830 // possible languages, and e.g. if you need a case-insensitive comparison,
831 // the details of that depend on the encoding & language in a complex way
832 // (actually underspecified in truetype, but also gigantic).
834 // But you can use the provided functions in two possible ways:
835 // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
836 // unicode-encoded names to try to find the font you want;
837 // you can run this before calling stbtt_InitFont()
839 // stbtt_GetFontNameString() lets you get any of the various strings
840 // from the file yourself and do your own comparisons on them.
841 // You have to have called stbtt_InitFont() first.
844 STBTT_DEF
int stbtt_FindMatchingFont(const unsigned char *fontdata
, const char *name
, int flags
);
845 // returns the offset (not index) of the font that matches, or -1 if none
846 // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
847 // if you use any other flag, use a font name like "Arial"; this checks
848 // the 'macStyle' header field; i don't know if fonts set this consistently
849 #define STBTT_MACSTYLE_DONTCARE 0
850 #define STBTT_MACSTYLE_BOLD 1
851 #define STBTT_MACSTYLE_ITALIC 2
852 #define STBTT_MACSTYLE_UNDERSCORE 4
853 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
855 STBTT_DEF
int stbtt_CompareUTF8toUTF16_bigendian(const char *s1
, int len1
, const char *s2
, int len2
);
856 // returns 1/0 whether the first string interpreted as utf8 is identical to
857 // the second string interpreted as big-endian utf16... useful for strings from next func
859 STBTT_DEF
const char *stbtt_GetFontNameString(const stbtt_fontinfo
*font
, int *length
, int platformID
, int encodingID
, int languageID
, int nameID
);
860 // returns the string (which may be big-endian double byte, e.g. for unicode)
861 // and puts the length in bytes in *length.
863 // some of the values for the IDs are below; for more see the truetype spec:
864 // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
865 // http://www.microsoft.com/typography/otspec/name.htm
868 STBTT_PLATFORM_ID_UNICODE
=0,
869 STBTT_PLATFORM_ID_MAC
=1,
870 STBTT_PLATFORM_ID_ISO
=2,
871 STBTT_PLATFORM_ID_MICROSOFT
=3
874 enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
875 STBTT_UNICODE_EID_UNICODE_1_0
=0,
876 STBTT_UNICODE_EID_UNICODE_1_1
=1,
877 STBTT_UNICODE_EID_ISO_10646
=2,
878 STBTT_UNICODE_EID_UNICODE_2_0_BMP
=3,
879 STBTT_UNICODE_EID_UNICODE_2_0_FULL
=4
882 enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
883 STBTT_MS_EID_SYMBOL
=0,
884 STBTT_MS_EID_UNICODE_BMP
=1,
885 STBTT_MS_EID_SHIFTJIS
=2,
886 STBTT_MS_EID_UNICODE_FULL
=10
889 enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
890 STBTT_MAC_EID_ROMAN
=0, STBTT_MAC_EID_ARABIC
=4,
891 STBTT_MAC_EID_JAPANESE
=1, STBTT_MAC_EID_HEBREW
=5,
892 STBTT_MAC_EID_CHINESE_TRAD
=2, STBTT_MAC_EID_GREEK
=6,
893 STBTT_MAC_EID_KOREAN
=3, STBTT_MAC_EID_RUSSIAN
=7
896 enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
897 // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
898 STBTT_MS_LANG_ENGLISH
=0x0409, STBTT_MS_LANG_ITALIAN
=0x0410,
899 STBTT_MS_LANG_CHINESE
=0x0804, STBTT_MS_LANG_JAPANESE
=0x0411,
900 STBTT_MS_LANG_DUTCH
=0x0413, STBTT_MS_LANG_KOREAN
=0x0412,
901 STBTT_MS_LANG_FRENCH
=0x040c, STBTT_MS_LANG_RUSSIAN
=0x0419,
902 STBTT_MS_LANG_GERMAN
=0x0407, STBTT_MS_LANG_SPANISH
=0x0409,
903 STBTT_MS_LANG_HEBREW
=0x040d, STBTT_MS_LANG_SWEDISH
=0x041D
906 enum { // languageID for STBTT_PLATFORM_ID_MAC
907 STBTT_MAC_LANG_ENGLISH
=0 , STBTT_MAC_LANG_JAPANESE
=11,
908 STBTT_MAC_LANG_ARABIC
=12, STBTT_MAC_LANG_KOREAN
=23,
909 STBTT_MAC_LANG_DUTCH
=4 , STBTT_MAC_LANG_RUSSIAN
=32,
910 STBTT_MAC_LANG_FRENCH
=1 , STBTT_MAC_LANG_SPANISH
=6 ,
911 STBTT_MAC_LANG_GERMAN
=2 , STBTT_MAC_LANG_SWEDISH
=5 ,
912 STBTT_MAC_LANG_HEBREW
=10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED
=33,
913 STBTT_MAC_LANG_ITALIAN
=3 , STBTT_MAC_LANG_CHINESE_TRAD
=19
920 #endif // __STB_INCLUDE_STB_TRUETYPE_H__
922 ///////////////////////////////////////////////////////////////////////////////
923 ///////////////////////////////////////////////////////////////////////////////
929 #ifdef STB_TRUETYPE_IMPLEMENTATION
931 #ifndef STBTT_MAX_OVERSAMPLE
932 #define STBTT_MAX_OVERSAMPLE 8
935 #if STBTT_MAX_OVERSAMPLE > 255
936 #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
939 typedef int stbtt__test_oversample_pow2
[(STBTT_MAX_OVERSAMPLE
& (STBTT_MAX_OVERSAMPLE
-1)) == 0 ? 1 : -1];
941 #ifndef STBTT_RASTERIZER_VERSION
942 #define STBTT_RASTERIZER_VERSION 2
945 //////////////////////////////////////////////////////////////////////////
947 // accessors to parse data from file
950 // on platforms that don't allow misaligned reads, if we want to allow
951 // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
953 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
954 #define ttCHAR(p) (* (stbtt_int8 *) (p))
955 #define ttFixed(p) ttLONG(p)
957 #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
959 #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
960 #define ttSHORT(p) (* (stbtt_int16 *) (p))
961 #define ttULONG(p) (* (stbtt_uint32 *) (p))
962 #define ttLONG(p) (* (stbtt_int32 *) (p))
966 static stbtt_uint16
ttUSHORT(const stbtt_uint8
*p
) { return p
[0]*256 + p
[1]; }
967 static stbtt_int16
ttSHORT(const stbtt_uint8
*p
) { return p
[0]*256 + p
[1]; }
968 static stbtt_uint32
ttULONG(const stbtt_uint8
*p
) { return (p
[0]<<24) + (p
[1]<<16) + (p
[2]<<8) + p
[3]; }
969 static stbtt_int32
ttLONG(const stbtt_uint8
*p
) { return (p
[0]<<24) + (p
[1]<<16) + (p
[2]<<8) + p
[3]; }
973 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
974 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
976 static int stbtt__isfont(const stbtt_uint8
*font
)
978 // check the version number
979 if (stbtt_tag4(font
, '1',0,0,0)) return 1; // TrueType 1
980 if (stbtt_tag(font
, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
981 if (stbtt_tag(font
, "OTTO")) return 1; // OpenType with CFF
982 if (stbtt_tag4(font
, 0,1,0,0)) return 1; // OpenType 1.0
986 // @OPTIMIZE: binary search
987 static stbtt_uint32
stbtt__find_table(stbtt_uint8
*data
, stbtt_uint32 fontstart
, const char *tag
)
989 stbtt_int32 num_tables
= ttUSHORT(data
+fontstart
+4);
990 stbtt_uint32 tabledir
= fontstart
+ 12;
992 for (i
=0; i
< num_tables
; ++i
) {
993 stbtt_uint32 loc
= tabledir
+ 16*i
;
994 if (stbtt_tag(data
+loc
+0, tag
))
995 return ttULONG(data
+loc
+8);
1000 STBTT_DEF
int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection
, int index
)
1002 // if it's just a font, there's only one valid index
1003 if (stbtt__isfont(font_collection
))
1004 return index
== 0 ? 0 : -1;
1006 // check if it's a TTC
1007 if (stbtt_tag(font_collection
, "ttcf")) {
1009 if (ttULONG(font_collection
+4) == 0x00010000 || ttULONG(font_collection
+4) == 0x00020000) {
1010 stbtt_int32 n
= ttLONG(font_collection
+8);
1013 return ttULONG(font_collection
+12+index
*4);
1019 STBTT_DEF
int stbtt_InitFont(stbtt_fontinfo
*info
, const unsigned char *data2
, int fontstart
)
1021 stbtt_uint8
*data
= (stbtt_uint8
*) data2
;
1022 stbtt_uint32 cmap
, t
;
1023 stbtt_int32 i
,numTables
;
1026 info
->fontstart
= fontstart
;
1028 cmap
= stbtt__find_table(data
, fontstart
, "cmap"); // required
1029 info
->loca
= stbtt__find_table(data
, fontstart
, "loca"); // required
1030 info
->head
= stbtt__find_table(data
, fontstart
, "head"); // required
1031 info
->glyf
= stbtt__find_table(data
, fontstart
, "glyf"); // required
1032 info
->hhea
= stbtt__find_table(data
, fontstart
, "hhea"); // required
1033 info
->hmtx
= stbtt__find_table(data
, fontstart
, "hmtx"); // required
1034 info
->kern
= stbtt__find_table(data
, fontstart
, "kern"); // not required
1035 if (!cmap
|| !info
->loca
|| !info
->head
|| !info
->glyf
|| !info
->hhea
|| !info
->hmtx
)
1038 t
= stbtt__find_table(data
, fontstart
, "maxp");
1040 info
->numGlyphs
= ttUSHORT(data
+t
+4);
1042 info
->numGlyphs
= 0xffff;
1044 // find a cmap encoding table we understand *now* to avoid searching
1045 // later. (todo: could make this installable)
1046 // the same regardless of glyph.
1047 numTables
= ttUSHORT(data
+ cmap
+ 2);
1048 info
->index_map
= 0;
1049 for (i
=0; i
< numTables
; ++i
) {
1050 stbtt_uint32 encoding_record
= cmap
+ 4 + 8 * i
;
1051 // find an encoding we understand:
1052 switch(ttUSHORT(data
+encoding_record
)) {
1053 case STBTT_PLATFORM_ID_MICROSOFT
:
1054 switch (ttUSHORT(data
+encoding_record
+2)) {
1055 case STBTT_MS_EID_UNICODE_BMP
:
1056 case STBTT_MS_EID_UNICODE_FULL
:
1058 info
->index_map
= cmap
+ ttULONG(data
+encoding_record
+4);
1062 case STBTT_PLATFORM_ID_UNICODE
:
1063 // Mac/iOS has these
1064 // all the encodingIDs are unicode, so we don't bother to check it
1065 info
->index_map
= cmap
+ ttULONG(data
+encoding_record
+4);
1069 if (info
->index_map
== 0)
1072 info
->indexToLocFormat
= ttUSHORT(data
+info
->head
+ 50);
1076 STBTT_DEF
int stbtt_FindGlyphIndex(const stbtt_fontinfo
*info
, int unicode_codepoint
)
1078 stbtt_uint8
*data
= info
->data
;
1079 stbtt_uint32 index_map
= info
->index_map
;
1081 stbtt_uint16 format
= ttUSHORT(data
+ index_map
+ 0);
1082 if (format
== 0) { // apple byte encoding
1083 stbtt_int32 bytes
= ttUSHORT(data
+ index_map
+ 2);
1084 if (unicode_codepoint
< bytes
-6)
1085 return ttBYTE(data
+ index_map
+ 6 + unicode_codepoint
);
1087 } else if (format
== 6) {
1088 stbtt_uint32 first
= ttUSHORT(data
+ index_map
+ 6);
1089 stbtt_uint32 count
= ttUSHORT(data
+ index_map
+ 8);
1090 if ((stbtt_uint32
) unicode_codepoint
>= first
&& (stbtt_uint32
) unicode_codepoint
< first
+count
)
1091 return ttUSHORT(data
+ index_map
+ 10 + (unicode_codepoint
- first
)*2);
1093 } else if (format
== 2) {
1094 STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
1096 } else if (format
== 4) { // standard mapping for windows fonts: binary search collection of ranges
1097 stbtt_uint16 segcount
= ttUSHORT(data
+index_map
+6) >> 1;
1098 stbtt_uint16 searchRange
= ttUSHORT(data
+index_map
+8) >> 1;
1099 stbtt_uint16 entrySelector
= ttUSHORT(data
+index_map
+10);
1100 stbtt_uint16 rangeShift
= ttUSHORT(data
+index_map
+12) >> 1;
1102 // do a binary search of the segments
1103 stbtt_uint32 endCount
= index_map
+ 14;
1104 stbtt_uint32 search
= endCount
;
1106 if (unicode_codepoint
> 0xffff)
1109 // they lie from endCount .. endCount + segCount
1110 // but searchRange is the nearest power of two, so...
1111 if (unicode_codepoint
>= ttUSHORT(data
+ search
+ rangeShift
*2))
1112 search
+= rangeShift
*2;
1114 // now decrement to bias correctly to find smallest
1116 while (entrySelector
) {
1119 end
= ttUSHORT(data
+ search
+ searchRange
*2);
1120 if (unicode_codepoint
> end
)
1121 search
+= searchRange
*2;
1127 stbtt_uint16 offset
, start
;
1128 stbtt_uint16 item
= (stbtt_uint16
) ((search
- endCount
) >> 1);
1130 STBTT_assert(unicode_codepoint
<= ttUSHORT(data
+ endCount
+ 2*item
));
1131 start
= ttUSHORT(data
+ index_map
+ 14 + segcount
*2 + 2 + 2*item
);
1132 if (unicode_codepoint
< start
)
1135 offset
= ttUSHORT(data
+ index_map
+ 14 + segcount
*6 + 2 + 2*item
);
1137 return (stbtt_uint16
) (unicode_codepoint
+ ttSHORT(data
+ index_map
+ 14 + segcount
*4 + 2 + 2*item
));
1139 return ttUSHORT(data
+ offset
+ (unicode_codepoint
-start
)*2 + index_map
+ 14 + segcount
*6 + 2 + 2*item
);
1141 } else if (format
== 12 || format
== 13) {
1142 stbtt_uint32 ngroups
= ttULONG(data
+index_map
+12);
1143 stbtt_int32 low
,high
;
1144 low
= 0; high
= (stbtt_int32
)ngroups
;
1145 // Binary search the right group.
1146 while (low
< high
) {
1147 stbtt_int32 mid
= low
+ ((high
-low
) >> 1); // rounds down, so low <= mid < high
1148 stbtt_uint32 start_char
= ttULONG(data
+index_map
+16+mid
*12);
1149 stbtt_uint32 end_char
= ttULONG(data
+index_map
+16+mid
*12+4);
1150 if ((stbtt_uint32
) unicode_codepoint
< start_char
)
1152 else if ((stbtt_uint32
) unicode_codepoint
> end_char
)
1155 stbtt_uint32 start_glyph
= ttULONG(data
+index_map
+16+mid
*12+8);
1157 return start_glyph
+ unicode_codepoint
-start_char
;
1158 else // format == 13
1162 return 0; // not found
1169 STBTT_DEF
int stbtt_GetCodepointShape(const stbtt_fontinfo
*info
, int unicode_codepoint
, stbtt_vertex
**vertices
)
1171 return stbtt_GetGlyphShape(info
, stbtt_FindGlyphIndex(info
, unicode_codepoint
), vertices
);
1174 static void stbtt_setvertex(stbtt_vertex
*v
, stbtt_uint8 type
, stbtt_int32 x
, stbtt_int32 y
, stbtt_int32 cx
, stbtt_int32 cy
)
1177 v
->x
= (stbtt_int16
) x
;
1178 v
->y
= (stbtt_int16
) y
;
1179 v
->cx
= (stbtt_int16
) cx
;
1180 v
->cy
= (stbtt_int16
) cy
;
1183 static int stbtt__GetGlyfOffset(const stbtt_fontinfo
*info
, int glyph_index
)
1187 if (glyph_index
>= info
->numGlyphs
) return -1; // glyph index out of range
1188 if (info
->indexToLocFormat
>= 2) return -1; // unknown index->glyph map format
1190 if (info
->indexToLocFormat
== 0) {
1191 g1
= info
->glyf
+ ttUSHORT(info
->data
+ info
->loca
+ glyph_index
* 2) * 2;
1192 g2
= info
->glyf
+ ttUSHORT(info
->data
+ info
->loca
+ glyph_index
* 2 + 2) * 2;
1194 g1
= info
->glyf
+ ttULONG (info
->data
+ info
->loca
+ glyph_index
* 4);
1195 g2
= info
->glyf
+ ttULONG (info
->data
+ info
->loca
+ glyph_index
* 4 + 4);
1198 return g1
==g2
? -1 : g1
; // if length is 0, return -1
1201 STBTT_DEF
int stbtt_GetGlyphBox(const stbtt_fontinfo
*info
, int glyph_index
, int *x0
, int *y0
, int *x1
, int *y1
)
1203 int g
= stbtt__GetGlyfOffset(info
, glyph_index
);
1204 if (g
< 0) return 0;
1206 if (x0
) *x0
= ttSHORT(info
->data
+ g
+ 2);
1207 if (y0
) *y0
= ttSHORT(info
->data
+ g
+ 4);
1208 if (x1
) *x1
= ttSHORT(info
->data
+ g
+ 6);
1209 if (y1
) *y1
= ttSHORT(info
->data
+ g
+ 8);
1213 STBTT_DEF
int stbtt_GetCodepointBox(const stbtt_fontinfo
*info
, int codepoint
, int *x0
, int *y0
, int *x1
, int *y1
)
1215 return stbtt_GetGlyphBox(info
, stbtt_FindGlyphIndex(info
,codepoint
), x0
,y0
,x1
,y1
);
1218 STBTT_DEF
int stbtt_IsGlyphEmpty(const stbtt_fontinfo
*info
, int glyph_index
)
1220 stbtt_int16 numberOfContours
;
1221 int g
= stbtt__GetGlyfOffset(info
, glyph_index
);
1222 if (g
< 0) return 1;
1223 numberOfContours
= ttSHORT(info
->data
+ g
);
1224 return numberOfContours
== 0;
1227 static int stbtt__close_shape(stbtt_vertex
*vertices
, int num_vertices
, int was_off
, int start_off
,
1228 stbtt_int32 sx
, stbtt_int32 sy
, stbtt_int32 scx
, stbtt_int32 scy
, stbtt_int32 cx
, stbtt_int32 cy
)
1232 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, (cx
+scx
)>>1, (cy
+scy
)>>1, cx
,cy
);
1233 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, sx
,sy
,scx
,scy
);
1236 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
,sx
,sy
,cx
,cy
);
1238 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vline
,sx
,sy
,0,0);
1240 return num_vertices
;
1243 STBTT_DEF
int stbtt_GetGlyphShape(const stbtt_fontinfo
*info
, int glyph_index
, stbtt_vertex
**pvertices
)
1245 stbtt_int16 numberOfContours
;
1246 stbtt_uint8
*endPtsOfContours
;
1247 stbtt_uint8
*data
= info
->data
;
1248 stbtt_vertex
*vertices
=0;
1250 int g
= stbtt__GetGlyfOffset(info
, glyph_index
);
1254 if (g
< 0) return 0;
1256 numberOfContours
= ttSHORT(data
+ g
);
1258 if (numberOfContours
> 0) {
1259 stbtt_uint8 flags
=0,flagcount
;
1260 stbtt_int32 ins
, i
,j
=0,m
,n
, next_move
, was_off
=0, off
, start_off
=0;
1261 stbtt_int32 x
,y
,cx
,cy
,sx
,sy
, scx
,scy
;
1262 stbtt_uint8
*points
;
1263 endPtsOfContours
= (data
+ g
+ 10);
1264 ins
= ttUSHORT(data
+ g
+ 10 + numberOfContours
* 2);
1265 points
= data
+ g
+ 10 + numberOfContours
* 2 + 2 + ins
;
1267 n
= 1+ttUSHORT(endPtsOfContours
+ numberOfContours
*2-2);
1269 m
= n
+ 2*numberOfContours
; // a loose bound on how many vertices we might need
1270 vertices
= (stbtt_vertex
*) STBTT_malloc(m
* sizeof(vertices
[0]), info
->userdata
);
1277 // in first pass, we load uninterpreted data into the allocated array
1278 // above, shifted to the end of the array so we won't overwrite it when
1279 // we create our final data starting from the front
1281 off
= m
- n
; // starting offset for uninterpreted data, regardless of how m ends up being calculated
1285 for (i
=0; i
< n
; ++i
) {
1286 if (flagcount
== 0) {
1289 flagcount
= *points
++;
1292 vertices
[off
+i
].type
= flags
;
1295 // now load x coordinates
1297 for (i
=0; i
< n
; ++i
) {
1298 flags
= vertices
[off
+i
].type
;
1300 stbtt_int16 dx
= *points
++;
1301 x
+= (flags
& 16) ? dx
: -dx
; // ???
1303 if (!(flags
& 16)) {
1304 x
= x
+ (stbtt_int16
) (points
[0]*256 + points
[1]);
1308 vertices
[off
+i
].x
= (stbtt_int16
) x
;
1311 // now load y coordinates
1313 for (i
=0; i
< n
; ++i
) {
1314 flags
= vertices
[off
+i
].type
;
1316 stbtt_int16 dy
= *points
++;
1317 y
+= (flags
& 32) ? dy
: -dy
; // ???
1319 if (!(flags
& 32)) {
1320 y
= y
+ (stbtt_int16
) (points
[0]*256 + points
[1]);
1324 vertices
[off
+i
].y
= (stbtt_int16
) y
;
1327 // now convert them to our format
1329 sx
= sy
= cx
= cy
= scx
= scy
= 0;
1330 for (i
=0; i
< n
; ++i
) {
1331 flags
= vertices
[off
+i
].type
;
1332 x
= (stbtt_int16
) vertices
[off
+i
].x
;
1333 y
= (stbtt_int16
) vertices
[off
+i
].y
;
1335 if (next_move
== i
) {
1337 num_vertices
= stbtt__close_shape(vertices
, num_vertices
, was_off
, start_off
, sx
,sy
,scx
,scy
,cx
,cy
);
1339 // now start the new one
1340 start_off
= !(flags
& 1);
1342 // if we start off with an off-curve point, then when we need to find a point on the curve
1343 // where we can start, and we need to save some state for when we wraparound.
1346 if (!(vertices
[off
+i
+1].type
& 1)) {
1347 // next point is also a curve point, so interpolate an on-point curve
1348 sx
= (x
+ (stbtt_int32
) vertices
[off
+i
+1].x
) >> 1;
1349 sy
= (y
+ (stbtt_int32
) vertices
[off
+i
+1].y
) >> 1;
1351 // otherwise just use the next point as our start point
1352 sx
= (stbtt_int32
) vertices
[off
+i
+1].x
;
1353 sy
= (stbtt_int32
) vertices
[off
+i
+1].y
;
1354 ++i
; // we're using point i+1 as the starting point, so skip it
1360 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vmove
,sx
,sy
,0,0);
1362 next_move
= 1 + ttUSHORT(endPtsOfContours
+j
*2);
1365 if (!(flags
& 1)) { // if it's a curve
1366 if (was_off
) // two off-curve control points in a row means interpolate an on-curve midpoint
1367 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, (cx
+x
)>>1, (cy
+y
)>>1, cx
, cy
);
1373 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vcurve
, x
,y
, cx
, cy
);
1375 stbtt_setvertex(&vertices
[num_vertices
++], STBTT_vline
, x
,y
,0,0);
1380 num_vertices
= stbtt__close_shape(vertices
, num_vertices
, was_off
, start_off
, sx
,sy
,scx
,scy
,cx
,cy
);
1381 } else if (numberOfContours
== -1) {
1384 stbtt_uint8
*comp
= data
+ g
+ 10;
1388 stbtt_uint16 flags
, gidx
;
1389 int comp_num_verts
= 0, i
;
1390 stbtt_vertex
*comp_verts
= 0, *tmp
= 0;
1391 float mtx
[6] = {1,0,0,1,0,0}, m
, n
;
1393 flags
= ttSHORT(comp
); comp
+=2;
1394 gidx
= ttSHORT(comp
); comp
+=2;
1396 if (flags
& 2) { // XY values
1397 if (flags
& 1) { // shorts
1398 mtx
[4] = ttSHORT(comp
); comp
+=2;
1399 mtx
[5] = ttSHORT(comp
); comp
+=2;
1401 mtx
[4] = ttCHAR(comp
); comp
+=1;
1402 mtx
[5] = ttCHAR(comp
); comp
+=1;
1406 // @TODO handle matching point
1409 if (flags
& (1<<3)) { // WE_HAVE_A_SCALE
1410 mtx
[0] = mtx
[3] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1411 mtx
[1] = mtx
[2] = 0;
1412 } else if (flags
& (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
1413 mtx
[0] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1414 mtx
[1] = mtx
[2] = 0;
1415 mtx
[3] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1416 } else if (flags
& (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
1417 mtx
[0] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1418 mtx
[1] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1419 mtx
[2] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1420 mtx
[3] = ttSHORT(comp
)/16384.0f
; comp
+=2;
1423 // Find transformation scales.
1424 m
= (float) STBTT_sqrt(mtx
[0]*mtx
[0] + mtx
[1]*mtx
[1]);
1425 n
= (float) STBTT_sqrt(mtx
[2]*mtx
[2] + mtx
[3]*mtx
[3]);
1427 // Get indexed glyph.
1428 comp_num_verts
= stbtt_GetGlyphShape(info
, gidx
, &comp_verts
);
1429 if (comp_num_verts
> 0) {
1430 // Transform vertices.
1431 for (i
= 0; i
< comp_num_verts
; ++i
) {
1432 stbtt_vertex
* v
= &comp_verts
[i
];
1433 stbtt_vertex_type x
,y
;
1435 v
->x
= (stbtt_vertex_type
)(m
* (mtx
[0]*x
+ mtx
[2]*y
+ mtx
[4]));
1436 v
->y
= (stbtt_vertex_type
)(n
* (mtx
[1]*x
+ mtx
[3]*y
+ mtx
[5]));
1438 v
->cx
= (stbtt_vertex_type
)(m
* (mtx
[0]*x
+ mtx
[2]*y
+ mtx
[4]));
1439 v
->cy
= (stbtt_vertex_type
)(n
* (mtx
[1]*x
+ mtx
[3]*y
+ mtx
[5]));
1442 tmp
= (stbtt_vertex
*)STBTT_malloc((num_vertices
+comp_num_verts
)*sizeof(stbtt_vertex
), info
->userdata
);
1444 if (vertices
) STBTT_free(vertices
, info
->userdata
);
1445 if (comp_verts
) STBTT_free(comp_verts
, info
->userdata
);
1448 if (num_vertices
> 0) STBTT_memcpy(tmp
, vertices
, num_vertices
*sizeof(stbtt_vertex
));
1449 STBTT_memcpy(tmp
+num_vertices
, comp_verts
, comp_num_verts
*sizeof(stbtt_vertex
));
1450 if (vertices
) STBTT_free(vertices
, info
->userdata
);
1452 STBTT_free(comp_verts
, info
->userdata
);
1453 num_vertices
+= comp_num_verts
;
1455 // More components ?
1456 more
= flags
& (1<<5);
1458 } else if (numberOfContours
< 0) {
1459 // @TODO other compound variations?
1462 // numberOfCounters == 0, do nothing
1465 *pvertices
= vertices
;
1466 return num_vertices
;
1469 STBTT_DEF
void stbtt_GetGlyphHMetrics(const stbtt_fontinfo
*info
, int glyph_index
, int *advanceWidth
, int *leftSideBearing
)
1471 stbtt_uint16 numOfLongHorMetrics
= ttUSHORT(info
->data
+info
->hhea
+ 34);
1472 if (glyph_index
< numOfLongHorMetrics
) {
1473 if (advanceWidth
) *advanceWidth
= ttSHORT(info
->data
+ info
->hmtx
+ 4*glyph_index
);
1474 if (leftSideBearing
) *leftSideBearing
= ttSHORT(info
->data
+ info
->hmtx
+ 4*glyph_index
+ 2);
1476 if (advanceWidth
) *advanceWidth
= ttSHORT(info
->data
+ info
->hmtx
+ 4*(numOfLongHorMetrics
-1));
1477 if (leftSideBearing
) *leftSideBearing
= ttSHORT(info
->data
+ info
->hmtx
+ 4*numOfLongHorMetrics
+ 2*(glyph_index
- numOfLongHorMetrics
));
1481 STBTT_DEF
int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo
*info
, int glyph1
, int glyph2
)
1483 stbtt_uint8
*data
= info
->data
+ info
->kern
;
1484 stbtt_uint32 needle
, straw
;
1487 // we only look at the first table. it must be 'horizontal' and format 0.
1490 if (ttUSHORT(data
+2) < 1) // number of tables, need at least 1
1492 if (ttUSHORT(data
+8) != 1) // horizontal flag must be set in format
1496 r
= ttUSHORT(data
+10) - 1;
1497 needle
= glyph1
<< 16 | glyph2
;
1500 straw
= ttULONG(data
+18+(m
*6)); // note: unaligned read
1503 else if (needle
> straw
)
1506 return ttSHORT(data
+22+(m
*6));
1511 STBTT_DEF
int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo
*info
, int ch1
, int ch2
)
1513 if (!info
->kern
) // if no kerning table, don't waste time looking up both codepoint->glyphs
1515 return stbtt_GetGlyphKernAdvance(info
, stbtt_FindGlyphIndex(info
,ch1
), stbtt_FindGlyphIndex(info
,ch2
));
1518 STBTT_DEF
void stbtt_GetCodepointHMetrics(const stbtt_fontinfo
*info
, int codepoint
, int *advanceWidth
, int *leftSideBearing
)
1520 stbtt_GetGlyphHMetrics(info
, stbtt_FindGlyphIndex(info
,codepoint
), advanceWidth
, leftSideBearing
);
1523 STBTT_DEF
void stbtt_GetFontVMetrics(const stbtt_fontinfo
*info
, int *ascent
, int *descent
, int *lineGap
)
1525 if (ascent
) *ascent
= ttSHORT(info
->data
+info
->hhea
+ 4);
1526 if (descent
) *descent
= ttSHORT(info
->data
+info
->hhea
+ 6);
1527 if (lineGap
) *lineGap
= ttSHORT(info
->data
+info
->hhea
+ 8);
1530 STBTT_DEF
void stbtt_GetFontBoundingBox(const stbtt_fontinfo
*info
, int *x0
, int *y0
, int *x1
, int *y1
)
1532 *x0
= ttSHORT(info
->data
+ info
->head
+ 36);
1533 *y0
= ttSHORT(info
->data
+ info
->head
+ 38);
1534 *x1
= ttSHORT(info
->data
+ info
->head
+ 40);
1535 *y1
= ttSHORT(info
->data
+ info
->head
+ 42);
1538 STBTT_DEF
float stbtt_ScaleForPixelHeight(const stbtt_fontinfo
*info
, float height
)
1540 int fheight
= ttSHORT(info
->data
+ info
->hhea
+ 4) - ttSHORT(info
->data
+ info
->hhea
+ 6);
1541 return (float) height
/ fheight
;
1544 STBTT_DEF
float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo
*info
, float pixels
)
1546 int unitsPerEm
= ttUSHORT(info
->data
+ info
->head
+ 18);
1547 return pixels
/ unitsPerEm
;
1550 STBTT_DEF
void stbtt_FreeShape(const stbtt_fontinfo
*info
, stbtt_vertex
*v
)
1552 STBTT_free(v
, info
->userdata
);
1555 //////////////////////////////////////////////////////////////////////////////
1557 // antialiasing software rasterizer
1560 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
)
1562 int x0
=0,y0
=0,x1
,y1
; // =0 suppresses compiler warning
1563 if (!stbtt_GetGlyphBox(font
, glyph
, &x0
,&y0
,&x1
,&y1
)) {
1564 // e.g. space character
1570 // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
1571 if (ix0
) *ix0
= STBTT_ifloor( x0
* scale_x
+ shift_x
);
1572 if (iy0
) *iy0
= STBTT_ifloor(-y1
* scale_y
+ shift_y
);
1573 if (ix1
) *ix1
= STBTT_iceil ( x1
* scale_x
+ shift_x
);
1574 if (iy1
) *iy1
= STBTT_iceil (-y0
* scale_y
+ shift_y
);
1578 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
)
1580 stbtt_GetGlyphBitmapBoxSubpixel(font
, glyph
, scale_x
, scale_y
,0.0f
,0.0f
, ix0
, iy0
, ix1
, iy1
);
1583 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
)
1585 stbtt_GetGlyphBitmapBoxSubpixel(font
, stbtt_FindGlyphIndex(font
,codepoint
), scale_x
, scale_y
,shift_x
,shift_y
, ix0
,iy0
,ix1
,iy1
);
1588 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
)
1590 stbtt_GetCodepointBitmapBoxSubpixel(font
, codepoint
, scale_x
, scale_y
,0.0f
,0.0f
, ix0
,iy0
,ix1
,iy1
);
1593 //////////////////////////////////////////////////////////////////////////////
1597 typedef struct stbtt__hheap_chunk
1599 struct stbtt__hheap_chunk
*next
;
1600 } stbtt__hheap_chunk
;
1602 typedef struct stbtt__hheap
1604 struct stbtt__hheap_chunk
*head
;
1606 int num_remaining_in_head_chunk
;
1609 static void *stbtt__hheap_alloc(stbtt__hheap
*hh
, size_t size
, void *userdata
)
1611 if (hh
->first_free
) {
1612 void *p
= hh
->first_free
;
1613 hh
->first_free
= * (void **) p
;
1616 if (hh
->num_remaining_in_head_chunk
== 0) {
1617 int count
= (size
< 32 ? 2000 : size
< 128 ? 800 : 100);
1618 stbtt__hheap_chunk
*c
= (stbtt__hheap_chunk
*) STBTT_malloc(sizeof(stbtt__hheap_chunk
) + size
* count
, userdata
);
1623 hh
->num_remaining_in_head_chunk
= count
;
1625 --hh
->num_remaining_in_head_chunk
;
1626 return (char *) (hh
->head
) + size
* hh
->num_remaining_in_head_chunk
;
1630 static void stbtt__hheap_free(stbtt__hheap
*hh
, void *p
)
1632 *(void **) p
= hh
->first_free
;
1636 static void stbtt__hheap_cleanup(stbtt__hheap
*hh
, void *userdata
)
1638 stbtt__hheap_chunk
*c
= hh
->head
;
1640 stbtt__hheap_chunk
*n
= c
->next
;
1641 STBTT_free(c
, userdata
);
1646 typedef struct stbtt__edge
{
1652 typedef struct stbtt__active_edge
1654 struct stbtt__active_edge
*next
;
1655 #if STBTT_RASTERIZER_VERSION==1
1659 #elif STBTT_RASTERIZER_VERSION==2
1665 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
1667 } stbtt__active_edge
;
1669 #if STBTT_RASTERIZER_VERSION == 1
1670 #define STBTT_FIXSHIFT 10
1671 #define STBTT_FIX (1 << STBTT_FIXSHIFT)
1672 #define STBTT_FIXMASK (STBTT_FIX-1)
1674 static stbtt__active_edge
*stbtt__new_active(stbtt__hheap
*hh
, stbtt__edge
*e
, int off_x
, float start_point
, void *userdata
)
1676 stbtt__active_edge
*z
= (stbtt__active_edge
*) stbtt__hheap_alloc(hh
, sizeof(*z
), userdata
);
1677 float dxdy
= (e
->x1
- e
->x0
) / (e
->y1
- e
->y0
);
1678 STBTT_assert(z
!= NULL
);
1681 // round dx down to avoid overshooting
1683 z
->dx
= -STBTT_ifloor(STBTT_FIX
* -dxdy
);
1685 z
->dx
= STBTT_ifloor(STBTT_FIX
* dxdy
);
1687 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
1688 z
->x
-= off_x
* STBTT_FIX
;
1692 z
->direction
= e
->invert
? 1 : -1;
1695 #elif STBTT_RASTERIZER_VERSION == 2
1696 static stbtt__active_edge
*stbtt__new_active(stbtt__hheap
*hh
, stbtt__edge
*e
, int off_x
, float start_point
, void *userdata
)
1698 stbtt__active_edge
*z
= (stbtt__active_edge
*) stbtt__hheap_alloc(hh
, sizeof(*z
), userdata
);
1699 float dxdy
= (e
->x1
- e
->x0
) / (e
->y1
- e
->y0
);
1700 STBTT_assert(z
!= NULL
);
1701 //STBTT_assert(e->y0 <= start_point);
1704 z
->fdy
= dxdy
!= 0.0f
? (1.0f
/dxdy
) : 0.0f
;
1705 z
->fx
= e
->x0
+ dxdy
* (start_point
- e
->y0
);
1707 z
->direction
= e
->invert
? 1.0f
: -1.0f
;
1714 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
1717 #if STBTT_RASTERIZER_VERSION == 1
1718 // note: this routine clips fills that extend off the edges... ideally this
1719 // wouldn't happen, but it could happen if the truetype glyph bounding boxes
1720 // are wrong, or if the user supplies a too-small bitmap
1721 static void stbtt__fill_active_edges(unsigned char *scanline
, int len
, stbtt__active_edge
*e
, int max_weight
)
1723 // non-zero winding fill
1728 // if we're currently at zero, we need to record the edge start point
1729 x0
= e
->x
; w
+= e
->direction
;
1731 int x1
= e
->x
; w
+= e
->direction
;
1732 // if we went to zero, we need to draw
1734 int i
= x0
>> STBTT_FIXSHIFT
;
1735 int j
= x1
>> STBTT_FIXSHIFT
;
1737 if (i
< len
&& j
>= 0) {
1739 // x0,x1 are the same pixel, so compute combined coverage
1740 scanline
[i
] = scanline
[i
] + (stbtt_uint8
) ((x1
- x0
) * max_weight
>> STBTT_FIXSHIFT
);
1742 if (i
>= 0) // add antialiasing for x0
1743 scanline
[i
] = scanline
[i
] + (stbtt_uint8
) (((STBTT_FIX
- (x0
& STBTT_FIXMASK
)) * max_weight
) >> STBTT_FIXSHIFT
);
1747 if (j
< len
) // add antialiasing for x1
1748 scanline
[j
] = scanline
[j
] + (stbtt_uint8
) (((x1
& STBTT_FIXMASK
) * max_weight
) >> STBTT_FIXSHIFT
);
1752 for (++i
; i
< j
; ++i
) // fill pixels between x0 and x1
1753 scanline
[i
] = scanline
[i
] + (stbtt_uint8
) max_weight
;
1763 static void stbtt__rasterize_sorted_edges(stbtt__bitmap
*result
, stbtt__edge
*e
, int n
, int vsubsample
, int off_x
, int off_y
, void *userdata
)
1765 stbtt__hheap hh
= { 0, 0, 0 };
1766 stbtt__active_edge
*active
= NULL
;
1768 int max_weight
= (255 / vsubsample
); // weight per vertical scanline
1769 int s
; // vertical subsample index
1770 unsigned char scanline_data
[512], *scanline
;
1772 if (result
->w
> 512)
1773 scanline
= (unsigned char *) STBTT_malloc(result
->w
, userdata
);
1775 scanline
= scanline_data
;
1777 y
= off_y
* vsubsample
;
1778 e
[n
].y0
= (off_y
+ result
->h
) * (float) vsubsample
+ 1;
1780 while (j
< result
->h
) {
1781 STBTT_memset(scanline
, 0, result
->w
);
1782 for (s
=0; s
< vsubsample
; ++s
) {
1783 // find center of pixel for this scanline
1784 float scan_y
= y
+ 0.5f
;
1785 stbtt__active_edge
**step
= &active
;
1787 // update all active edges;
1788 // remove all active edges that terminate before the center of this scanline
1790 stbtt__active_edge
* z
= *step
;
1791 if (z
->ey
<= scan_y
) {
1792 *step
= z
->next
; // delete from list
1793 STBTT_assert(z
->direction
);
1795 stbtt__hheap_free(&hh
, z
);
1797 z
->x
+= z
->dx
; // advance to position for current scanline
1798 step
= &((*step
)->next
); // advance through list
1802 // resort the list if needed
1806 while (*step
&& (*step
)->next
) {
1807 if ((*step
)->x
> (*step
)->next
->x
) {
1808 stbtt__active_edge
*t
= *step
;
1809 stbtt__active_edge
*q
= t
->next
;
1816 step
= &(*step
)->next
;
1818 if (!changed
) break;
1821 // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
1822 while (e
->y0
<= scan_y
) {
1823 if (e
->y1
> scan_y
) {
1824 stbtt__active_edge
*z
= stbtt__new_active(&hh
, e
, off_x
, scan_y
, userdata
);
1826 // find insertion point
1829 else if (z
->x
< active
->x
) {
1834 // find thing to insert AFTER
1835 stbtt__active_edge
*p
= active
;
1836 while (p
->next
&& p
->next
->x
< z
->x
)
1838 // at this point, p->next->x is NOT < z->x
1847 // now process all active edges in XOR fashion
1849 stbtt__fill_active_edges(scanline
, result
->w
, active
, max_weight
);
1853 STBTT_memcpy(result
->pixels
+ j
* result
->stride
, scanline
, result
->w
);
1857 stbtt__hheap_cleanup(&hh
, userdata
);
1859 if (scanline
!= scanline_data
)
1860 STBTT_free(scanline
, userdata
);
1863 #elif STBTT_RASTERIZER_VERSION == 2
1865 // the edge passed in here does not cross the vertical line at x or the vertical line at x+1
1866 // (i.e. it has already been clipped to those)
1867 static void stbtt__handle_clipped_edge(float *scanline
, int x
, stbtt__active_edge
*e
, float x0
, float y0
, float x1
, float y1
)
1869 if (y0
== y1
) return;
1870 STBTT_assert(y0
< y1
);
1871 STBTT_assert(e
->sy
<= e
->ey
);
1872 if (y0
> e
->ey
) return;
1873 if (y1
< e
->sy
) return;
1875 x0
+= (x1
-x0
) * (e
->sy
- y0
) / (y1
-y0
);
1879 x1
+= (x1
-x0
) * (e
->ey
- y1
) / (y1
-y0
);
1884 STBTT_assert(x1
<= x
+1);
1886 STBTT_assert(x1
>= x
);
1888 STBTT_assert(x1
<= x
);
1890 STBTT_assert(x1
>= x
+1);
1892 STBTT_assert(x1
>= x
&& x1
<= x
+1);
1894 if (x0
<= x
&& x1
<= x
)
1895 scanline
[x
] += e
->direction
* (y1
-y0
);
1896 else if (x0
>= x
+1 && x1
>= x
+1)
1899 STBTT_assert(x0
>= x
&& x0
<= x
+1 && x1
>= x
&& x1
<= x
+1);
1900 scanline
[x
] += e
->direction
* (y1
-y0
) * (1-((x0
-x
)+(x1
-x
))/2); // coverage = 1 - average x position
1904 static void stbtt__fill_active_edges_new(float *scanline
, float *scanline_fill
, int len
, stbtt__active_edge
*e
, float y_top
)
1906 float y_bottom
= y_top
+1;
1909 // brute force every pixel
1911 // compute intersection points with top & bottom
1912 STBTT_assert(e
->ey
>= y_top
);
1918 stbtt__handle_clipped_edge(scanline
,(int) x0
,e
, x0
,y_top
, x0
,y_bottom
);
1919 stbtt__handle_clipped_edge(scanline_fill
-1,(int) x0
+1,e
, x0
,y_top
, x0
,y_bottom
);
1921 stbtt__handle_clipped_edge(scanline_fill
-1,0,e
, x0
,y_top
, x0
,y_bottom
);
1928 float x_top
, x_bottom
;
1931 STBTT_assert(e
->sy
<= y_bottom
&& e
->ey
>= y_top
);
1933 // compute endpoints of line segment clipped to this scanline (if the
1934 // line segment starts on this scanline. x0 is the intersection of the
1935 // line with y_top, but that may be off the line segment.
1936 if (e
->sy
> y_top
) {
1937 x_top
= x0
+ dx
* (e
->sy
- y_top
);
1943 if (e
->ey
< y_bottom
) {
1944 x_bottom
= x0
+ dx
* (e
->ey
- y_top
);
1951 if (x_top
>= 0 && x_bottom
>= 0 && x_top
< len
&& x_bottom
< len
) {
1952 // from here on, we don't have to range check x values
1954 if ((int) x_top
== (int) x_bottom
) {
1956 // simple case, only spans one pixel
1957 int x
= (int) x_top
;
1959 STBTT_assert(x
>= 0 && x
< len
);
1960 scanline
[x
] += e
->direction
* (1-((x_top
- x
) + (x_bottom
-x
))/2) * height
;
1961 scanline_fill
[x
] += e
->direction
* height
; // everything right of this pixel is filled
1964 float y_crossing
, step
, sign
, area
;
1966 if (x_top
> x_bottom
) {
1967 // flip scanline vertically; signed area is the same
1969 sy0
= y_bottom
- (sy0
- y_top
);
1970 sy1
= y_bottom
- (sy1
- y_top
);
1971 t
= sy0
, sy0
= sy1
, sy1
= t
;
1972 t
= x_bottom
, x_bottom
= x_top
, x_top
= t
;
1975 t
= x0
, x0
= xb
, xb
= t
;
1979 x2
= (int) x_bottom
;
1980 // compute intersection with y axis at x1+1
1981 y_crossing
= (x1
+1 - x0
) * dy
+ y_top
;
1983 sign
= e
->direction
;
1984 // area of the rectangle covered from y0..y_crossing
1985 area
= sign
* (y_crossing
-sy0
);
1986 // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
1987 scanline
[x1
] += area
* (1-((x_top
- x1
)+(x1
+1-x1
))/2);
1990 for (x
= x1
+1; x
< x2
; ++x
) {
1991 scanline
[x
] += area
+ step
/2;
1994 y_crossing
+= dy
* (x2
- (x1
+1));
1996 STBTT_assert(fabs(area
) <= 1.01f
);
1998 scanline
[x2
] += area
+ sign
* (1-((x2
-x2
)+(x_bottom
-x2
))/2) * (sy1
-y_crossing
);
2000 scanline_fill
[x2
] += sign
* (sy1
-sy0
);
2003 // if edge goes outside of box we're drawing, we require
2004 // clipping logic. since this does not match the intended use
2005 // of this library, we use a different, very slow brute
2006 // force implementation
2008 for (x
=0; x
< len
; ++x
) {
2011 // there can be up to two intersections with the pixel. any intersection
2012 // with left or right edges can be handled by splitting into two (or three)
2013 // regions. intersections with top & bottom do not necessitate case-wise logic.
2015 // the old way of doing this found the intersections with the left & right edges,
2016 // then used some simple logic to produce up to three segments in sorted order
2017 // from top-to-bottom. however, this had a problem: if an x edge was epsilon
2018 // across the x border, then the corresponding y position might not be distinct
2019 // from the other y segment, and it might ignored as an empty segment. to avoid
2020 // that, we need to explicitly produce segments based on x positions.
2022 // rename variables to clear pairs
2024 float x1
= (float) (x
);
2025 float x2
= (float) (x
+1);
2027 float y3
= y_bottom
;
2030 // x = e->x + e->dx * (y-y_top)
2031 // (y-y_top) = (x - e->x) / e->dx
2032 // y = (x - e->x) / e->dx + y_top
2033 y1
= (x
- x0
) / dx
+ y_top
;
2034 y2
= (x
+1 - x0
) / dx
+ y_top
;
2036 if (x0
< x1
&& x3
> x2
) { // three segments descending down-right
2037 stbtt__handle_clipped_edge(scanline
,x
,e
, x0
,y0
, x1
,y1
);
2038 stbtt__handle_clipped_edge(scanline
,x
,e
, x1
,y1
, x2
,y2
);
2039 stbtt__handle_clipped_edge(scanline
,x
,e
, x2
,y2
, x3
,y3
);
2040 } else if (x3
< x1
&& x0
> x2
) { // three segments descending down-left
2041 stbtt__handle_clipped_edge(scanline
,x
,e
, x0
,y0
, x2
,y2
);
2042 stbtt__handle_clipped_edge(scanline
,x
,e
, x2
,y2
, x1
,y1
);
2043 stbtt__handle_clipped_edge(scanline
,x
,e
, x1
,y1
, x3
,y3
);
2044 } else if (x0
< x1
&& x3
> x1
) { // two segments across x, down-right
2045 stbtt__handle_clipped_edge(scanline
,x
,e
, x0
,y0
, x1
,y1
);
2046 stbtt__handle_clipped_edge(scanline
,x
,e
, x1
,y1
, x3
,y3
);
2047 } else if (x3
< x1
&& x0
> x1
) { // two segments across x, down-left
2048 stbtt__handle_clipped_edge(scanline
,x
,e
, x0
,y0
, x1
,y1
);
2049 stbtt__handle_clipped_edge(scanline
,x
,e
, x1
,y1
, x3
,y3
);
2050 } else if (x0
< x2
&& x3
> x2
) { // two segments across x+1, down-right
2051 stbtt__handle_clipped_edge(scanline
,x
,e
, x0
,y0
, x2
,y2
);
2052 stbtt__handle_clipped_edge(scanline
,x
,e
, x2
,y2
, x3
,y3
);
2053 } else if (x3
< x2
&& x0
> x2
) { // two segments across x+1, down-left
2054 stbtt__handle_clipped_edge(scanline
,x
,e
, x0
,y0
, x2
,y2
);
2055 stbtt__handle_clipped_edge(scanline
,x
,e
, x2
,y2
, x3
,y3
);
2056 } else { // one segment
2057 stbtt__handle_clipped_edge(scanline
,x
,e
, x0
,y0
, x3
,y3
);
2066 // directly AA rasterize edges w/o supersampling
2067 static void stbtt__rasterize_sorted_edges(stbtt__bitmap
*result
, stbtt__edge
*e
, int n
, int vsubsample
, int off_x
, int off_y
, void *userdata
)
2069 stbtt__hheap hh
= { 0, 0, 0 };
2070 stbtt__active_edge
*active
= NULL
;
2072 float scanline_data
[129], *scanline
, *scanline2
;
2075 scanline
= (float *) STBTT_malloc((result
->w
*2+1) * sizeof(float), userdata
);
2077 scanline
= scanline_data
;
2079 scanline2
= scanline
+ result
->w
;
2082 e
[n
].y0
= (float) (off_y
+ result
->h
) + 1;
2084 while (j
< result
->h
) {
2085 // find center of pixel for this scanline
2086 float scan_y_top
= y
+ 0.0f
;
2087 float scan_y_bottom
= y
+ 1.0f
;
2088 stbtt__active_edge
**step
= &active
;
2090 STBTT_memset(scanline
, 0, result
->w
*sizeof(scanline
[0]));
2091 STBTT_memset(scanline2
, 0, (result
->w
+1)*sizeof(scanline
[0]));
2093 // update all active edges;
2094 // remove all active edges that terminate before the top of this scanline
2096 stbtt__active_edge
* z
= *step
;
2097 if (z
->ey
<= scan_y_top
) {
2098 *step
= z
->next
; // delete from list
2099 STBTT_assert(z
->direction
);
2101 stbtt__hheap_free(&hh
, z
);
2103 step
= &((*step
)->next
); // advance through list
2107 // insert all edges that start before the bottom of this scanline
2108 while (e
->y0
<= scan_y_bottom
) {
2109 if (e
->y0
!= e
->y1
) {
2110 stbtt__active_edge
*z
= stbtt__new_active(&hh
, e
, off_x
, scan_y_top
, userdata
);
2112 STBTT_assert(z
->ey
>= scan_y_top
);
2121 // now process all active edges
2123 stbtt__fill_active_edges_new(scanline
, scanline2
+1, result
->w
, active
, scan_y_top
);
2127 for (i
=0; i
< result
->w
; ++i
) {
2130 sum
+= scanline2
[i
];
2131 k
= scanline
[i
] + sum
;
2132 k
= (float) fabs(k
)*255 + 0.5f
;
2134 if (m
> 255) m
= 255;
2135 result
->pixels
[j
*result
->stride
+ i
] = (unsigned char) m
;
2138 // advance all the edges
2141 stbtt__active_edge
*z
= *step
;
2142 z
->fx
+= z
->fdx
; // advance to position for current scanline
2143 step
= &((*step
)->next
); // advance through list
2150 stbtt__hheap_cleanup(&hh
, userdata
);
2152 if (scanline
!= scanline_data
)
2153 STBTT_free(scanline
, userdata
);
2156 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2159 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
2161 static void stbtt__sort_edges_ins_sort(stbtt__edge
*p
, int n
)
2164 for (i
=1; i
< n
; ++i
) {
2165 stbtt__edge t
= p
[i
], *a
= &t
;
2168 stbtt__edge
*b
= &p
[j
-1];
2169 int c
= STBTT__COMPARE(a
,b
);
2179 static void stbtt__sort_edges_quicksort(stbtt__edge
*p
, int n
)
2181 /* threshhold for transitioning to insertion sort */
2184 int c01
,c12
,c
,m
,i
,j
;
2186 /* compute median of three */
2188 c01
= STBTT__COMPARE(&p
[0],&p
[m
]);
2189 c12
= STBTT__COMPARE(&p
[m
],&p
[n
-1]);
2190 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
2192 /* otherwise, we'll need to swap something else to middle */
2194 c
= STBTT__COMPARE(&p
[0],&p
[n
-1]);
2195 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
2196 /* 0<mid && mid>n: 0>n => 0; 0<n => n */
2197 z
= (c
== c12
) ? 0 : n
-1;
2202 /* now p[m] is the median-of-three */
2203 /* swap it to the beginning so it won't move around */
2208 /* partition loop */
2212 /* handling of equality is crucial here */
2213 /* for sentinels & efficiency with duplicates */
2215 if (!STBTT__COMPARE(&p
[i
], &p
[0])) break;
2218 if (!STBTT__COMPARE(&p
[0], &p
[j
])) break;
2220 /* make sure we haven't crossed */
2229 /* recurse on smaller side, iterate on larger */
2231 stbtt__sort_edges_quicksort(p
,j
);
2235 stbtt__sort_edges_quicksort(p
+i
, n
-i
);
2241 static void stbtt__sort_edges(stbtt__edge
*p
, int n
)
2243 stbtt__sort_edges_quicksort(p
, n
);
2244 stbtt__sort_edges_ins_sort(p
, n
);
2252 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
)
2254 float y_scale_inv
= invert
? -scale_y
: scale_y
;
2257 #if STBTT_RASTERIZER_VERSION == 1
2258 int vsubsample
= result
->h
< 8 ? 15 : 5;
2259 #elif STBTT_RASTERIZER_VERSION == 2
2262 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2264 // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
2266 // now we have to blow out the windings into explicit edge lists
2268 for (i
=0; i
< windings
; ++i
)
2271 e
= (stbtt__edge
*) STBTT_malloc(sizeof(*e
) * (n
+1), userdata
); // add an extra one as a sentinel
2276 for (i
=0; i
< windings
; ++i
) {
2277 stbtt__point
*p
= pts
+ m
;
2280 for (k
=0; k
< wcount
[i
]; j
=k
++) {
2282 // skip the edge if horizontal
2283 if (p
[j
].y
== p
[k
].y
)
2285 // add edge from j to k to the list
2287 if (invert
? p
[j
].y
> p
[k
].y
: p
[j
].y
< p
[k
].y
) {
2291 e
[n
].x0
= p
[a
].x
* scale_x
+ shift_x
;
2292 e
[n
].y0
= (p
[a
].y
* y_scale_inv
+ shift_y
) * vsubsample
;
2293 e
[n
].x1
= p
[b
].x
* scale_x
+ shift_x
;
2294 e
[n
].y1
= (p
[b
].y
* y_scale_inv
+ shift_y
) * vsubsample
;
2299 // now sort the edges by their highest point (should snap to integer, and then by x)
2300 //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
2301 stbtt__sort_edges(e
, n
);
2303 // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
2304 stbtt__rasterize_sorted_edges(result
, e
, n
, vsubsample
, off_x
, off_y
, userdata
);
2306 STBTT_free(e
, userdata
);
2309 static void stbtt__add_point(stbtt__point
*points
, int n
, float x
, float y
)
2311 if (!points
) return; // during first pass, it's unallocated
2316 // tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
2317 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
)
2320 float mx
= (x0
+ 2*x1
+ x2
)/4;
2321 float my
= (y0
+ 2*y1
+ y2
)/4;
2322 // versus directly drawn line
2323 float dx
= (x0
+x2
)/2 - mx
;
2324 float dy
= (y0
+y2
)/2 - my
;
2325 if (n
> 16) // 65536 segments on one curve better be enough!
2327 if (dx
*dx
+dy
*dy
> objspace_flatness_squared
) { // half-pixel error allowed... need to be smaller if AA
2328 stbtt__tesselate_curve(points
, num_points
, x0
,y0
, (x0
+x1
)/2.0f
,(y0
+y1
)/2.0f
, mx
,my
, objspace_flatness_squared
,n
+1);
2329 stbtt__tesselate_curve(points
, num_points
, mx
,my
, (x1
+x2
)/2.0f
,(y1
+y2
)/2.0f
, x2
,y2
, objspace_flatness_squared
,n
+1);
2331 stbtt__add_point(points
, *num_points
,x2
,y2
);
2332 *num_points
= *num_points
+1;
2337 // returns number of contours
2338 static stbtt__point
*stbtt_FlattenCurves(stbtt_vertex
*vertices
, int num_verts
, float objspace_flatness
, int **contour_lengths
, int *num_contours
, void *userdata
)
2340 stbtt__point
*points
=0;
2343 float objspace_flatness_squared
= objspace_flatness
* objspace_flatness
;
2344 int i
,n
=0,start
=0, pass
;
2346 // count how many "moves" there are to get the contour count
2347 for (i
=0; i
< num_verts
; ++i
)
2348 if (vertices
[i
].type
== STBTT_vmove
)
2352 if (n
== 0) return 0;
2354 *contour_lengths
= (int *) STBTT_malloc(sizeof(**contour_lengths
) * n
, userdata
);
2356 if (*contour_lengths
== 0) {
2361 // make two passes through the points so we don't need to realloc
2362 for (pass
=0; pass
< 2; ++pass
) {
2365 points
= (stbtt__point
*) STBTT_malloc(num_points
* sizeof(points
[0]), userdata
);
2366 if (points
== NULL
) goto error
;
2370 for (i
=0; i
< num_verts
; ++i
) {
2371 switch (vertices
[i
].type
) {
2373 // start the next contour
2375 (*contour_lengths
)[n
] = num_points
- start
;
2379 x
= vertices
[i
].x
, y
= vertices
[i
].y
;
2380 stbtt__add_point(points
, num_points
++, x
,y
);
2383 x
= vertices
[i
].x
, y
= vertices
[i
].y
;
2384 stbtt__add_point(points
, num_points
++, x
, y
);
2387 stbtt__tesselate_curve(points
, &num_points
, x
,y
,
2388 vertices
[i
].cx
, vertices
[i
].cy
,
2389 vertices
[i
].x
, vertices
[i
].y
,
2390 objspace_flatness_squared
, 0);
2391 x
= vertices
[i
].x
, y
= vertices
[i
].y
;
2395 (*contour_lengths
)[n
] = num_points
- start
;
2400 STBTT_free(points
, userdata
);
2401 STBTT_free(*contour_lengths
, userdata
);
2402 *contour_lengths
= 0;
2407 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
)
2409 float scale
= scale_x
> scale_y
? scale_y
: scale_x
;
2410 int winding_count
, *winding_lengths
;
2411 stbtt__point
*windings
= stbtt_FlattenCurves(vertices
, num_verts
, flatness_in_pixels
/ scale
, &winding_lengths
, &winding_count
, userdata
);
2413 stbtt__rasterize(result
, windings
, winding_lengths
, winding_count
, scale_x
, scale_y
, shift_x
, shift_y
, x_off
, y_off
, invert
, userdata
);
2414 STBTT_free(winding_lengths
, userdata
);
2415 STBTT_free(windings
, userdata
);
2419 STBTT_DEF
void stbtt_FreeBitmap(unsigned char *bitmap
, void *userdata
)
2421 STBTT_free(bitmap
, userdata
);
2424 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
)
2426 int ix0
,iy0
,ix1
,iy1
;
2428 stbtt_vertex
*vertices
;
2429 int num_verts
= stbtt_GetGlyphShape(info
, glyph
, &vertices
);
2431 if (scale_x
== 0) scale_x
= scale_y
;
2433 if (scale_x
== 0) return NULL
;
2437 stbtt_GetGlyphBitmapBoxSubpixel(info
, glyph
, scale_x
, scale_y
, shift_x
, shift_y
, &ix0
,&iy0
,&ix1
,&iy1
);
2439 // now we get the size
2440 gbm
.w
= (ix1
- ix0
);
2441 gbm
.h
= (iy1
- iy0
);
2442 gbm
.pixels
= NULL
; // in case we error
2444 if (width
) *width
= gbm
.w
;
2445 if (height
) *height
= gbm
.h
;
2446 if (xoff
) *xoff
= ix0
;
2447 if (yoff
) *yoff
= iy0
;
2449 if (gbm
.w
&& gbm
.h
) {
2450 gbm
.pixels
= (unsigned char *) STBTT_malloc(gbm
.w
* gbm
.h
, info
->userdata
);
2454 stbtt_Rasterize(&gbm
, 0.35f
, vertices
, num_verts
, scale_x
, scale_y
, shift_x
, shift_y
, ix0
, iy0
, 1, info
->userdata
);
2457 STBTT_free(vertices
, info
->userdata
);
2461 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
)
2463 return stbtt_GetGlyphBitmapSubpixel(info
, scale_x
, scale_y
, 0.0f
, 0.0f
, glyph
, width
, height
, xoff
, yoff
);
2466 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
)
2469 stbtt_vertex
*vertices
;
2470 int num_verts
= stbtt_GetGlyphShape(info
, glyph
, &vertices
);
2473 stbtt_GetGlyphBitmapBoxSubpixel(info
, glyph
, scale_x
, scale_y
, shift_x
, shift_y
, &ix0
,&iy0
,0,0);
2474 gbm
.pixels
= output
;
2477 gbm
.stride
= out_stride
;
2480 stbtt_Rasterize(&gbm
, 0.35f
, vertices
, num_verts
, scale_x
, scale_y
, shift_x
, shift_y
, ix0
,iy0
, 1, info
->userdata
);
2482 STBTT_free(vertices
, info
->userdata
);
2485 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
)
2487 stbtt_MakeGlyphBitmapSubpixel(info
, output
, out_w
, out_h
, out_stride
, scale_x
, scale_y
, 0.0f
,0.0f
, glyph
);
2490 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
)
2492 return stbtt_GetGlyphBitmapSubpixel(info
, scale_x
, scale_y
,shift_x
,shift_y
, stbtt_FindGlyphIndex(info
,codepoint
), width
,height
,xoff
,yoff
);
2495 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
)
2497 stbtt_MakeGlyphBitmapSubpixel(info
, output
, out_w
, out_h
, out_stride
, scale_x
, scale_y
, shift_x
, shift_y
, stbtt_FindGlyphIndex(info
,codepoint
));
2500 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
)
2502 return stbtt_GetCodepointBitmapSubpixel(info
, scale_x
, scale_y
, 0.0f
,0.0f
, codepoint
, width
,height
,xoff
,yoff
);
2505 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
)
2507 stbtt_MakeCodepointBitmapSubpixel(info
, output
, out_w
, out_h
, out_stride
, scale_x
, scale_y
, 0.0f
,0.0f
, codepoint
);
2510 //////////////////////////////////////////////////////////////////////////////
2514 // This is SUPER-CRAPPY packing to keep source code small
2516 STBTT_DEF
int stbtt_BakeFontBitmap(const unsigned char *data
, int offset
, // font location (use offset=0 for plain .ttf)
2517 float pixel_height
, // height of font in pixels
2518 unsigned char *pixels
, int pw
, int ph
, // bitmap to be filled in
2519 int first_char
, int num_chars
, // characters to bake
2520 stbtt_bakedchar
*chardata
)
2523 int x
,y
,bottom_y
, i
;
2526 if (!stbtt_InitFont(&f
, data
, offset
))
2528 STBTT_memset(pixels
, 0, pw
*ph
); // background of 0 around pixels
2532 scale
= stbtt_ScaleForPixelHeight(&f
, pixel_height
);
2534 for (i
=0; i
< num_chars
; ++i
) {
2535 int advance
, lsb
, x0
,y0
,x1
,y1
,gw
,gh
;
2536 int g
= stbtt_FindGlyphIndex(&f
, first_char
+ i
);
2537 stbtt_GetGlyphHMetrics(&f
, g
, &advance
, &lsb
);
2538 stbtt_GetGlyphBitmapBox(&f
, g
, scale
,scale
, &x0
,&y0
,&x1
,&y1
);
2541 if (x
+ gw
+ 1 >= pw
)
2542 y
= bottom_y
, x
= 1; // advance to next row
2543 if (y
+ gh
+ 1 >= ph
) // check if it fits vertically AFTER potentially moving to next row
2545 STBTT_assert(x
+gw
< pw
);
2546 STBTT_assert(y
+gh
< ph
);
2547 stbtt_MakeGlyphBitmap(&f
, pixels
+x
+y
*pw
, gw
,gh
,pw
, scale
,scale
, g
);
2548 chardata
[i
].x0
= (stbtt_int16
) x
;
2549 chardata
[i
].y0
= (stbtt_int16
) y
;
2550 chardata
[i
].x1
= (stbtt_int16
) (x
+ gw
);
2551 chardata
[i
].y1
= (stbtt_int16
) (y
+ gh
);
2552 chardata
[i
].xadvance
= scale
* advance
;
2553 chardata
[i
].xoff
= (float) x0
;
2554 chardata
[i
].yoff
= (float) y0
;
2556 if (y
+gh
+1 > bottom_y
)
2562 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
)
2564 float d3d_bias
= opengl_fillrule
? 0 : -0.5f
;
2565 float ipw
= 1.0f
/ pw
, iph
= 1.0f
/ ph
;
2566 stbtt_bakedchar
*b
= chardata
+ char_index
;
2567 int round_x
= STBTT_ifloor((*xpos
+ b
->xoff
) + 0.5f
);
2568 int round_y
= STBTT_ifloor((*ypos
+ b
->yoff
) + 0.5f
);
2570 q
->x0
= round_x
+ d3d_bias
;
2571 q
->y0
= round_y
+ d3d_bias
;
2572 q
->x1
= round_x
+ b
->x1
- b
->x0
+ d3d_bias
;
2573 q
->y1
= round_y
+ b
->y1
- b
->y0
+ d3d_bias
;
2575 q
->s0
= b
->x0
* ipw
;
2576 q
->t0
= b
->y0
* iph
;
2577 q
->s1
= b
->x1
* ipw
;
2578 q
->t1
= b
->y1
* iph
;
2580 *xpos
+= b
->xadvance
;
2583 //////////////////////////////////////////////////////////////////////////////
2585 // rectangle packing replacement routines if you don't have stb_rect_pack.h
2588 #ifndef STB_RECT_PACK_VERSION
2590 #define STBTT__NOTUSED(v) (void)(v)
2592 #define STBTT__NOTUSED(v) (void)sizeof(v)
2595 typedef int stbrp_coord
;
2597 ////////////////////////////////////////////////////////////////////////////////////
2600 // COMPILER WARNING ?!?!? //
2603 // if you get a compile warning due to these symbols being defined more than //
2604 // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
2606 ////////////////////////////////////////////////////////////////////////////////////
2622 int id
,w
,h
,was_packed
;
2625 static void stbrp_init_target(stbrp_context
*con
, int pw
, int ph
, stbrp_node
*nodes
, int num_nodes
)
2632 STBTT__NOTUSED(nodes
);
2633 STBTT__NOTUSED(num_nodes
);
2636 static void stbrp_pack_rects(stbrp_context
*con
, stbrp_rect
*rects
, int num_rects
)
2639 for (i
=0; i
< num_rects
; ++i
) {
2640 if (con
->x
+ rects
[i
].w
> con
->width
) {
2642 con
->y
= con
->bottom_y
;
2644 if (con
->y
+ rects
[i
].h
> con
->height
)
2646 rects
[i
].x
= con
->x
;
2647 rects
[i
].y
= con
->y
;
2648 rects
[i
].was_packed
= 1;
2649 con
->x
+= rects
[i
].w
;
2650 if (con
->y
+ rects
[i
].h
> con
->bottom_y
)
2651 con
->bottom_y
= con
->y
+ rects
[i
].h
;
2653 for ( ; i
< num_rects
; ++i
)
2654 rects
[i
].was_packed
= 0;
2658 //////////////////////////////////////////////////////////////////////////////
2662 // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
2663 // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
2665 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
)
2667 stbrp_context
*context
= (stbrp_context
*) STBTT_malloc(sizeof(*context
) ,alloc_context
);
2668 int num_nodes
= pw
- padding
;
2669 stbrp_node
*nodes
= (stbrp_node
*) STBTT_malloc(sizeof(*nodes
) * num_nodes
,alloc_context
);
2671 if (context
== NULL
|| nodes
== NULL
) {
2672 if (context
!= NULL
) STBTT_free(context
, alloc_context
);
2673 if (nodes
!= NULL
) STBTT_free(nodes
, alloc_context
);
2677 spc
->user_allocator_context
= alloc_context
;
2680 spc
->pixels
= pixels
;
2681 spc
->pack_info
= context
;
2683 spc
->padding
= padding
;
2684 spc
->stride_in_bytes
= stride_in_bytes
!= 0 ? stride_in_bytes
: pw
;
2685 spc
->h_oversample
= 1;
2686 spc
->v_oversample
= 1;
2688 stbrp_init_target(context
, pw
-padding
, ph
-padding
, nodes
, num_nodes
);
2691 STBTT_memset(pixels
, 0, pw
*ph
); // background of 0 around pixels
2696 STBTT_DEF
void stbtt_PackEnd (stbtt_pack_context
*spc
)
2698 STBTT_free(spc
->nodes
, spc
->user_allocator_context
);
2699 STBTT_free(spc
->pack_info
, spc
->user_allocator_context
);
2702 STBTT_DEF
void stbtt_PackSetOversampling(stbtt_pack_context
*spc
, unsigned int h_oversample
, unsigned int v_oversample
)
2704 STBTT_assert(h_oversample
<= STBTT_MAX_OVERSAMPLE
);
2705 STBTT_assert(v_oversample
<= STBTT_MAX_OVERSAMPLE
);
2706 if (h_oversample
<= STBTT_MAX_OVERSAMPLE
)
2707 spc
->h_oversample
= h_oversample
;
2708 if (v_oversample
<= STBTT_MAX_OVERSAMPLE
)
2709 spc
->v_oversample
= v_oversample
;
2712 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
2714 static void stbtt__h_prefilter(unsigned char *pixels
, int w
, int h
, int stride_in_bytes
, unsigned int kernel_width
)
2716 unsigned char buffer
[STBTT_MAX_OVERSAMPLE
];
2717 int safe_w
= w
- kernel_width
;
2719 STBTT_memset(buffer
, 0, STBTT_MAX_OVERSAMPLE
); // suppress bogus warning from VS2013 -analyze
2720 for (j
=0; j
< h
; ++j
) {
2723 STBTT_memset(buffer
, 0, kernel_width
);
2727 // make kernel_width a constant in common cases so compiler can optimize out the divide
2728 switch (kernel_width
) {
2730 for (i
=0; i
<= safe_w
; ++i
) {
2731 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2732 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2733 pixels
[i
] = (unsigned char) (total
/ 2);
2737 for (i
=0; i
<= safe_w
; ++i
) {
2738 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2739 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2740 pixels
[i
] = (unsigned char) (total
/ 3);
2744 for (i
=0; i
<= safe_w
; ++i
) {
2745 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2746 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2747 pixels
[i
] = (unsigned char) (total
/ 4);
2751 for (i
=0; i
<= safe_w
; ++i
) {
2752 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2753 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2754 pixels
[i
] = (unsigned char) (total
/ 5);
2758 for (i
=0; i
<= safe_w
; ++i
) {
2759 total
+= pixels
[i
] - buffer
[i
& STBTT__OVER_MASK
];
2760 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
];
2761 pixels
[i
] = (unsigned char) (total
/ kernel_width
);
2766 for (; i
< w
; ++i
) {
2767 STBTT_assert(pixels
[i
] == 0);
2768 total
-= buffer
[i
& STBTT__OVER_MASK
];
2769 pixels
[i
] = (unsigned char) (total
/ kernel_width
);
2772 pixels
+= stride_in_bytes
;
2776 static void stbtt__v_prefilter(unsigned char *pixels
, int w
, int h
, int stride_in_bytes
, unsigned int kernel_width
)
2778 unsigned char buffer
[STBTT_MAX_OVERSAMPLE
];
2779 int safe_h
= h
- kernel_width
;
2781 STBTT_memset(buffer
, 0, STBTT_MAX_OVERSAMPLE
); // suppress bogus warning from VS2013 -analyze
2782 for (j
=0; j
< w
; ++j
) {
2785 STBTT_memset(buffer
, 0, kernel_width
);
2789 // make kernel_width a constant in common cases so compiler can optimize out the divide
2790 switch (kernel_width
) {
2792 for (i
=0; i
<= safe_h
; ++i
) {
2793 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2794 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2795 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ 2);
2799 for (i
=0; i
<= safe_h
; ++i
) {
2800 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2801 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2802 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ 3);
2806 for (i
=0; i
<= safe_h
; ++i
) {
2807 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2808 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2809 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ 4);
2813 for (i
=0; i
<= safe_h
; ++i
) {
2814 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2815 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2816 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ 5);
2820 for (i
=0; i
<= safe_h
; ++i
) {
2821 total
+= pixels
[i
*stride_in_bytes
] - buffer
[i
& STBTT__OVER_MASK
];
2822 buffer
[(i
+kernel_width
) & STBTT__OVER_MASK
] = pixels
[i
*stride_in_bytes
];
2823 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ kernel_width
);
2828 for (; i
< h
; ++i
) {
2829 STBTT_assert(pixels
[i
*stride_in_bytes
] == 0);
2830 total
-= buffer
[i
& STBTT__OVER_MASK
];
2831 pixels
[i
*stride_in_bytes
] = (unsigned char) (total
/ kernel_width
);
2838 static float stbtt__oversample_shift(int oversample
)
2843 // The prefilter is a box filter of width "oversample",
2844 // which shifts phase by (oversample - 1)/2 pixels in
2845 // oversampled space. We want to shift in the opposite
2846 // direction to counter this.
2847 return (float)-(oversample
- 1) / (2.0f
* (float)oversample
);
2850 // rects array must be big enough to accommodate all characters in the given ranges
2851 STBTT_DEF
int stbtt_PackFontRangesGatherRects(stbtt_pack_context
*spc
, stbtt_fontinfo
*info
, stbtt_pack_range
*ranges
, int num_ranges
, stbrp_rect
*rects
)
2856 for (i
=0; i
< num_ranges
; ++i
) {
2857 float fh
= ranges
[i
].font_size
;
2858 float scale
= fh
> 0 ? stbtt_ScaleForPixelHeight(info
, fh
) : stbtt_ScaleForMappingEmToPixels(info
, -fh
);
2859 ranges
[i
].h_oversample
= (unsigned char) spc
->h_oversample
;
2860 ranges
[i
].v_oversample
= (unsigned char) spc
->v_oversample
;
2861 for (j
=0; j
< ranges
[i
].num_chars
; ++j
) {
2863 int codepoint
= ranges
[i
].array_of_unicode_codepoints
== NULL
? ranges
[i
].first_unicode_codepoint_in_range
+ j
: ranges
[i
].array_of_unicode_codepoints
[j
];
2864 int glyph
= stbtt_FindGlyphIndex(info
, codepoint
);
2865 stbtt_GetGlyphBitmapBoxSubpixel(info
,glyph
,
2866 scale
* spc
->h_oversample
,
2867 scale
* spc
->v_oversample
,
2870 rects
[k
].w
= (stbrp_coord
) (x1
-x0
+ spc
->padding
+ spc
->h_oversample
-1);
2871 rects
[k
].h
= (stbrp_coord
) (y1
-y0
+ spc
->padding
+ spc
->v_oversample
-1);
2879 // rects array must be big enough to accommodate all characters in the given ranges
2880 STBTT_DEF
int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context
*spc
, stbtt_fontinfo
*info
, stbtt_pack_range
*ranges
, int num_ranges
, stbrp_rect
*rects
)
2882 int i
,j
,k
, return_value
= 1;
2884 // save current values
2885 int old_h_over
= spc
->h_oversample
;
2886 int old_v_over
= spc
->v_oversample
;
2889 for (i
=0; i
< num_ranges
; ++i
) {
2890 float fh
= ranges
[i
].font_size
;
2891 float scale
= fh
> 0 ? stbtt_ScaleForPixelHeight(info
, fh
) : stbtt_ScaleForMappingEmToPixels(info
, -fh
);
2892 float recip_h
,recip_v
,sub_x
,sub_y
;
2893 spc
->h_oversample
= ranges
[i
].h_oversample
;
2894 spc
->v_oversample
= ranges
[i
].v_oversample
;
2895 recip_h
= 1.0f
/ spc
->h_oversample
;
2896 recip_v
= 1.0f
/ spc
->v_oversample
;
2897 sub_x
= stbtt__oversample_shift(spc
->h_oversample
);
2898 sub_y
= stbtt__oversample_shift(spc
->v_oversample
);
2899 for (j
=0; j
< ranges
[i
].num_chars
; ++j
) {
2900 stbrp_rect
*r
= &rects
[k
];
2901 if (r
->was_packed
) {
2902 stbtt_packedchar
*bc
= &ranges
[i
].chardata_for_range
[j
];
2903 int advance
, lsb
, x0
,y0
,x1
,y1
;
2904 int codepoint
= ranges
[i
].array_of_unicode_codepoints
== NULL
? ranges
[i
].first_unicode_codepoint_in_range
+ j
: ranges
[i
].array_of_unicode_codepoints
[j
];
2905 int glyph
= stbtt_FindGlyphIndex(info
, codepoint
);
2906 stbrp_coord pad
= (stbrp_coord
) spc
->padding
;
2908 // pad on left and top
2913 stbtt_GetGlyphHMetrics(info
, glyph
, &advance
, &lsb
);
2914 stbtt_GetGlyphBitmapBox(info
, glyph
,
2915 scale
* spc
->h_oversample
,
2916 scale
* spc
->v_oversample
,
2918 stbtt_MakeGlyphBitmapSubpixel(info
,
2919 spc
->pixels
+ r
->x
+ r
->y
*spc
->stride_in_bytes
,
2920 r
->w
- spc
->h_oversample
+1,
2921 r
->h
- spc
->v_oversample
+1,
2922 spc
->stride_in_bytes
,
2923 scale
* spc
->h_oversample
,
2924 scale
* spc
->v_oversample
,
2928 if (spc
->h_oversample
> 1)
2929 stbtt__h_prefilter(spc
->pixels
+ r
->x
+ r
->y
*spc
->stride_in_bytes
,
2930 r
->w
, r
->h
, spc
->stride_in_bytes
,
2933 if (spc
->v_oversample
> 1)
2934 stbtt__v_prefilter(spc
->pixels
+ r
->x
+ r
->y
*spc
->stride_in_bytes
,
2935 r
->w
, r
->h
, spc
->stride_in_bytes
,
2938 bc
->x0
= (stbtt_int16
) r
->x
;
2939 bc
->y0
= (stbtt_int16
) r
->y
;
2940 bc
->x1
= (stbtt_int16
) (r
->x
+ r
->w
);
2941 bc
->y1
= (stbtt_int16
) (r
->y
+ r
->h
);
2942 bc
->xadvance
= scale
* advance
;
2943 bc
->xoff
= (float) x0
* recip_h
+ sub_x
;
2944 bc
->yoff
= (float) y0
* recip_v
+ sub_y
;
2945 bc
->xoff2
= (x0
+ r
->w
) * recip_h
+ sub_x
;
2946 bc
->yoff2
= (y0
+ r
->h
) * recip_v
+ sub_y
;
2948 return_value
= 0; // if any fail, report failure
2955 // restore original values
2956 spc
->h_oversample
= old_h_over
;
2957 spc
->v_oversample
= old_v_over
;
2959 return return_value
;
2962 STBTT_DEF
void stbtt_PackFontRangesPackRects(stbtt_pack_context
*spc
, stbrp_rect
*rects
, int num_rects
)
2964 stbrp_pack_rects((stbrp_context
*) spc
->pack_info
, rects
, num_rects
);
2967 STBTT_DEF
int stbtt_PackFontRanges(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, stbtt_pack_range
*ranges
, int num_ranges
)
2969 stbtt_fontinfo info
;
2970 int i
,j
,n
, return_value
= 1;
2971 //stbrp_context *context = (stbrp_context *) spc->pack_info;
2974 // flag all characters as NOT packed
2975 for (i
=0; i
< num_ranges
; ++i
)
2976 for (j
=0; j
< ranges
[i
].num_chars
; ++j
)
2977 ranges
[i
].chardata_for_range
[j
].x0
=
2978 ranges
[i
].chardata_for_range
[j
].y0
=
2979 ranges
[i
].chardata_for_range
[j
].x1
=
2980 ranges
[i
].chardata_for_range
[j
].y1
= 0;
2983 for (i
=0; i
< num_ranges
; ++i
)
2984 n
+= ranges
[i
].num_chars
;
2986 rects
= (stbrp_rect
*) STBTT_malloc(sizeof(*rects
) * n
, spc
->user_allocator_context
);
2990 info
.userdata
= spc
->user_allocator_context
;
2991 stbtt_InitFont(&info
, fontdata
, stbtt_GetFontOffsetForIndex(fontdata
,font_index
));
2993 n
= stbtt_PackFontRangesGatherRects(spc
, &info
, ranges
, num_ranges
, rects
);
2995 stbtt_PackFontRangesPackRects(spc
, rects
, n
);
2997 return_value
= stbtt_PackFontRangesRenderIntoRects(spc
, &info
, ranges
, num_ranges
, rects
);
2999 STBTT_free(rects
, spc
->user_allocator_context
);
3000 return return_value
;
3003 STBTT_DEF
int stbtt_PackFontRange(stbtt_pack_context
*spc
, unsigned char *fontdata
, int font_index
, float font_size
,
3004 int first_unicode_codepoint_in_range
, int num_chars_in_range
, stbtt_packedchar
*chardata_for_range
)
3006 stbtt_pack_range range
;
3007 range
.first_unicode_codepoint_in_range
= first_unicode_codepoint_in_range
;
3008 range
.array_of_unicode_codepoints
= NULL
;
3009 range
.num_chars
= num_chars_in_range
;
3010 range
.chardata_for_range
= chardata_for_range
;
3011 range
.font_size
= font_size
;
3012 return stbtt_PackFontRanges(spc
, fontdata
, font_index
, &range
, 1);
3015 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
)
3017 float ipw
= 1.0f
/ pw
, iph
= 1.0f
/ ph
;
3018 stbtt_packedchar
*b
= chardata
+ char_index
;
3020 if (align_to_integer
) {
3021 float x
= (float) STBTT_ifloor((*xpos
+ b
->xoff
) + 0.5f
);
3022 float y
= (float) STBTT_ifloor((*ypos
+ b
->yoff
) + 0.5f
);
3025 q
->x1
= x
+ b
->xoff2
- b
->xoff
;
3026 q
->y1
= y
+ b
->yoff2
- b
->yoff
;
3028 q
->x0
= *xpos
+ b
->xoff
;
3029 q
->y0
= *ypos
+ b
->yoff
;
3030 q
->x1
= *xpos
+ b
->xoff2
;
3031 q
->y1
= *ypos
+ b
->yoff2
;
3034 q
->s0
= b
->x0
* ipw
;
3035 q
->t0
= b
->y0
* iph
;
3036 q
->s1
= b
->x1
* ipw
;
3037 q
->t1
= b
->y1
* iph
;
3039 *xpos
+= b
->xadvance
;
3043 //////////////////////////////////////////////////////////////////////////////
3045 // font name matching -- recommended not to use this
3048 // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
3049 static stbtt_int32
stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8
*s1
, stbtt_int32 len1
, const stbtt_uint8
*s2
, stbtt_int32 len2
)
3053 // convert utf16 to utf8 and compare the results while converting
3055 stbtt_uint16 ch
= s2
[0]*256 + s2
[1];
3057 if (i
>= len1
) return -1;
3058 if (s1
[i
++] != ch
) return -1;
3059 } else if (ch
< 0x800) {
3060 if (i
+1 >= len1
) return -1;
3061 if (s1
[i
++] != 0xc0 + (ch
>> 6)) return -1;
3062 if (s1
[i
++] != 0x80 + (ch
& 0x3f)) return -1;
3063 } else if (ch
>= 0xd800 && ch
< 0xdc00) {
3065 stbtt_uint16 ch2
= s2
[2]*256 + s2
[3];
3066 if (i
+3 >= len1
) return -1;
3067 c
= ((ch
- 0xd800) << 10) + (ch2
- 0xdc00) + 0x10000;
3068 if (s1
[i
++] != 0xf0 + (c
>> 18)) return -1;
3069 if (s1
[i
++] != 0x80 + ((c
>> 12) & 0x3f)) return -1;
3070 if (s1
[i
++] != 0x80 + ((c
>> 6) & 0x3f)) return -1;
3071 if (s1
[i
++] != 0x80 + ((c
) & 0x3f)) return -1;
3072 s2
+= 2; // plus another 2 below
3074 } else if (ch
>= 0xdc00 && ch
< 0xe000) {
3077 if (i
+2 >= len1
) return -1;
3078 if (s1
[i
++] != 0xe0 + (ch
>> 12)) return -1;
3079 if (s1
[i
++] != 0x80 + ((ch
>> 6) & 0x3f)) return -1;
3080 if (s1
[i
++] != 0x80 + ((ch
) & 0x3f)) return -1;
3088 STBTT_DEF
int stbtt_CompareUTF8toUTF16_bigendian(const char *s1
, int len1
, const char *s2
, int len2
)
3090 return len1
== stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8
*) s1
, len1
, (const stbtt_uint8
*) s2
, len2
);
3093 // returns results in whatever encoding you request... but note that 2-byte encodings
3094 // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
3095 STBTT_DEF
const char *stbtt_GetFontNameString(const stbtt_fontinfo
*font
, int *length
, int platformID
, int encodingID
, int languageID
, int nameID
)
3097 stbtt_int32 i
,count
,stringOffset
;
3098 stbtt_uint8
*fc
= font
->data
;
3099 stbtt_uint32 offset
= font
->fontstart
;
3100 stbtt_uint32 nm
= stbtt__find_table(fc
, offset
, "name");
3101 if (!nm
) return NULL
;
3103 count
= ttUSHORT(fc
+nm
+2);
3104 stringOffset
= nm
+ ttUSHORT(fc
+nm
+4);
3105 for (i
=0; i
< count
; ++i
) {
3106 stbtt_uint32 loc
= nm
+ 6 + 12 * i
;
3107 if (platformID
== ttUSHORT(fc
+loc
+0) && encodingID
== ttUSHORT(fc
+loc
+2)
3108 && languageID
== ttUSHORT(fc
+loc
+4) && nameID
== ttUSHORT(fc
+loc
+6)) {
3109 *length
= ttUSHORT(fc
+loc
+8);
3110 return (const char *) (fc
+stringOffset
+ttUSHORT(fc
+loc
+10));
3116 static int stbtt__matchpair(stbtt_uint8
*fc
, stbtt_uint32 nm
, stbtt_uint8
*name
, stbtt_int32 nlen
, stbtt_int32 target_id
, stbtt_int32 next_id
)
3119 stbtt_int32 count
= ttUSHORT(fc
+nm
+2);
3120 stbtt_int32 stringOffset
= nm
+ ttUSHORT(fc
+nm
+4);
3122 for (i
=0; i
< count
; ++i
) {
3123 stbtt_uint32 loc
= nm
+ 6 + 12 * i
;
3124 stbtt_int32 id
= ttUSHORT(fc
+loc
+6);
3125 if (id
== target_id
) {
3126 // find the encoding
3127 stbtt_int32 platform
= ttUSHORT(fc
+loc
+0), encoding
= ttUSHORT(fc
+loc
+2), language
= ttUSHORT(fc
+loc
+4);
3129 // is this a Unicode encoding?
3130 if (platform
== 0 || (platform
== 3 && encoding
== 1) || (platform
== 3 && encoding
== 10)) {
3131 stbtt_int32 slen
= ttUSHORT(fc
+loc
+8);
3132 stbtt_int32 off
= ttUSHORT(fc
+loc
+10);
3134 // check if there's a prefix match
3135 stbtt_int32 matchlen
= stbtt__CompareUTF8toUTF16_bigendian_prefix(name
, nlen
, fc
+stringOffset
+off
,slen
);
3136 if (matchlen
>= 0) {
3137 // check for target_id+1 immediately following, with same encoding & language
3138 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
) {
3139 slen
= ttUSHORT(fc
+loc
+12+8);
3140 off
= ttUSHORT(fc
+loc
+12+10);
3142 if (matchlen
== nlen
)
3144 } else if (matchlen
< nlen
&& name
[matchlen
] == ' ') {
3146 if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name
+matchlen
), nlen
-matchlen
, (char*)(fc
+stringOffset
+off
),slen
))
3150 // if nothing immediately following
3151 if (matchlen
== nlen
)
3157 // @TODO handle other encodings
3163 static int stbtt__matches(stbtt_uint8
*fc
, stbtt_uint32 offset
, stbtt_uint8
*name
, stbtt_int32 flags
)
3165 stbtt_int32 nlen
= (stbtt_int32
) STBTT_strlen((char *) name
);
3167 if (!stbtt__isfont(fc
+offset
)) return 0;
3169 // check italics/bold/underline flags in macStyle...
3171 hd
= stbtt__find_table(fc
, offset
, "head");
3172 if ((ttUSHORT(fc
+hd
+44) & 7) != (flags
& 7)) return 0;
3175 nm
= stbtt__find_table(fc
, offset
, "name");
3179 // if we checked the macStyle flags, then just check the family and ignore the subfamily
3180 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 16, -1)) return 1;
3181 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 1, -1)) return 1;
3182 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 3, -1)) return 1;
3184 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 16, 17)) return 1;
3185 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 1, 2)) return 1;
3186 if (stbtt__matchpair(fc
, nm
, name
, nlen
, 3, -1)) return 1;
3192 STBTT_DEF
int stbtt_FindMatchingFont(const unsigned char *font_collection
, const char *name_utf8
, stbtt_int32 flags
)
3196 stbtt_int32 off
= stbtt_GetFontOffsetForIndex(font_collection
, i
);
3197 if (off
< 0) return off
;
3198 if (stbtt__matches((stbtt_uint8
*) font_collection
, off
, (stbtt_uint8
*) name_utf8
, flags
))
3203 #endif // STB_TRUETYPE_IMPLEMENTATION
3206 // FULL VERSION HISTORY
3208 // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
3209 // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
3210 // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
3211 // allow PackFontRanges to pack and render in separate phases;
3212 // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
3213 // fixed an assert() bug in the new rasterizer
3214 // replace assert() with STBTT_assert() in new rasterizer
3215 // 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
3216 // also more precise AA rasterizer, except if shapes overlap
3217 // remove need for STBTT_sort
3218 // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
3219 // 1.04 (2015-04-15) typo in example
3220 // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
3221 // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
3222 // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
3223 // non-oversampled; STBTT_POINT_SIZE for packed case only
3224 // 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
3225 // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
3226 // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
3227 // 0.8b (2014-07-07) fix a warning
3228 // 0.8 (2014-05-25) fix a few more warnings
3229 // 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
3230 // 0.6c (2012-07-24) improve documentation
3231 // 0.6b (2012-07-20) fix a few more warnings
3232 // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
3233 // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
3234 // 0.5 (2011-12-09) bugfixes:
3235 // subpixel glyph renderer computed wrong bounding box
3236 // first vertex of shape can be off-curve (FreeSans)
3237 // 0.4b (2011-12-03) fixed an error in the font baking example
3238 // 0.4 (2011-12-01) kerning, subpixel rendering (tor)
3240 // codepoint-to-glyph conversion using table fmt=12
3241 // codepoint-to-glyph conversion using table fmt=4
3242 // stbtt_GetBakedQuad with non-square texture (Zer)
3243 // updated Hello World! sample to use kerning and subpixel
3244 // fixed some warnings
3245 // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
3246 // userdata, malloc-from-userdata, non-zero fill (stb)
3247 // 0.2 (2009-03-11) Fix unsigned/signed char warnings
3248 // 0.1 (2009-03-09) First public release