1 // stb_truetype.h - v1.08 - public domain 2 // authored from 2009-2015 by Sean Barrett / RAD Game Tools 3 // 4 // This library processes TrueType files: 5 // parse files 6 // extract glyph metrics 7 // extract glyph shapes 8 // render glyphs to one-channel bitmaps with antialiasing (box filter) 9 // 10 // Todo: 11 // non-MS cmaps 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? 18 // 19 // ADDITIONAL CONTRIBUTORS 20 // 21 // Mikko Mononen: compound shape support, more cmap formats 22 // Tor Andersson: kerning, subpixel rendering 23 // 24 // Bug/warning reports/fixes: 25 // "Zer" on mollyrocket (with fix) 26 // Cass Everitt 27 // stoiko (Haemimont Games) 28 // Brian Hook 29 // Walter van Niftrik 30 // David Gow 31 // David Given 32 // Ivan-Assen Ivanov 33 // Anthony Pesch 34 // Johan Duparc 35 // Hou Qiming 36 // Fabian "ryg" Giesen 37 // Martins Mozeiko 38 // Cap Petschulat 39 // Omar Cornut 40 // github:aloucks 41 // Peter LaValle 42 // Sergey Popov 43 // Giumo X. Clanjor 44 // Higor Euripedes 45 // 46 // Misc other: 47 // Ryan Gordon 48 // 49 // VERSION HISTORY 50 // 51 // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges 52 // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; 53 // variant PackFontRanges to pack and render in separate phases; 54 // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); 55 // fixed an assert() bug in the new rasterizer 56 // replace assert() with STBTT_assert() in new rasterizer 57 // 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) 58 // also more precise AA rasterizer, except if shapes overlap 59 // remove need for STBTT_sort 60 // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC 61 // 1.04 (2015-04-15) typo in example 62 // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes 63 // 64 // Full history can be found at the end of this file. 65 // 66 // LICENSE 67 // 68 // This software is in the public domain. Where that dedication is not 69 // recognized, you are granted a perpetual, irrevocable license to copy, 70 // distribute, and modify this file as you see fit. 71 // 72 // USAGE 73 // 74 // Include this file in whatever places neeed to refer to it. In ONE C/C++ 75 // file, write: 76 // #define STB_TRUETYPE_IMPLEMENTATION 77 // before the #include of this file. This expands out the actual 78 // implementation into that C/C++ file. 79 // 80 // To make the implementation private to the file that generates the implementation, 81 // #define STBTT_STATIC 82 // 83 // Simple 3D API (don't ship this, but it's fine for tools and quick start) 84 // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture 85 // stbtt_GetBakedQuad() -- compute quad to draw for a given char 86 // 87 // Improved 3D API (more shippable): 88 // #include "stb_rect_pack.h" -- optional, but you really want it 89 // stbtt_PackBegin() 90 // stbtt_PackSetOversample() -- for improved quality on small fonts 91 // stbtt_PackFontRanges() -- pack and renders 92 // stbtt_PackEnd() 93 // stbtt_GetPackedQuad() 94 // 95 // "Load" a font file from a memory buffer (you have to keep the buffer loaded) 96 // stbtt_InitFont() 97 // stbtt_GetFontOffsetForIndex() -- use for TTC font collections 98 // 99 // Render a unicode codepoint to a bitmap 100 // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap 101 // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide 102 // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be 103 // 104 // Character advance/positioning 105 // stbtt_GetCodepointHMetrics() 106 // stbtt_GetFontVMetrics() 107 // stbtt_GetCodepointKernAdvance() 108 // 109 // Starting with version 1.06, the rasterizer was replaced with a new, 110 // faster and generally-more-precise rasterizer. The new rasterizer more 111 // accurately measures pixel coverage for anti-aliasing, except in the case 112 // where multiple shapes overlap, in which case it overestimates the AA pixel 113 // coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If 114 // this turns out to be a problem, you can re-enable the old rasterizer with 115 // #define STBTT_RASTERIZER_VERSION 1 116 // which will incur about a 15% speed hit. 117 // 118 // ADDITIONAL DOCUMENTATION 119 // 120 // Immediately after this block comment are a series of sample programs. 121 // 122 // After the sample programs is the "header file" section. This section 123 // includes documentation for each API function. 124 // 125 // Some important concepts to understand to use this library: 126 // 127 // Codepoint 128 // Characters are defined by unicode codepoints, e.g. 65 is 129 // uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is 130 // the hiragana for "ma". 131 // 132 // Glyph 133 // A visual character shape (every codepoint is rendered as 134 // some glyph) 135 // 136 // Glyph index 137 // A font-specific integer ID representing a glyph 138 // 139 // Baseline 140 // Glyph shapes are defined relative to a baseline, which is the 141 // bottom of uppercase characters. Characters extend both above 142 // and below the baseline. 143 // 144 // Current Point 145 // As you draw text to the screen, you keep track of a "current point" 146 // which is the origin of each character. The current point's vertical 147 // position is the baseline. Even "baked fonts" use this model. 148 // 149 // Vertical Font Metrics 150 // The vertical qualities of the font, used to vertically position 151 // and space the characters. See docs for stbtt_GetFontVMetrics. 152 // 153 // Font Size in Pixels or Points 154 // The preferred interface for specifying font sizes in stb_truetype 155 // is to specify how tall the font's vertical extent should be in pixels. 156 // If that sounds good enough, skip the next paragraph. 157 // 158 // Most font APIs instead use "points", which are a common typographic 159 // measurement for describing font size, defined as 72 points per inch. 160 // stb_truetype provides a point API for compatibility. However, true 161 // "per inch" conventions don't make much sense on computer displays 162 // since they different monitors have different number of pixels per 163 // inch. For example, Windows traditionally uses a convention that 164 // there are 96 pixels per inch, thus making 'inch' measurements have 165 // nothing to do with inches, and thus effectively defining a point to 166 // be 1.333 pixels. Additionally, the TrueType font data provides 167 // an explicit scale factor to scale a given font's glyphs to points, 168 // but the author has observed that this scale factor is often wrong 169 // for non-commercial fonts, thus making fonts scaled in points 170 // according to the TrueType spec incoherently sized in practice. 171 // 172 // ADVANCED USAGE 173 // 174 // Quality: 175 // 176 // - Use the functions with Subpixel at the end to allow your characters 177 // to have subpixel positioning. Since the font is anti-aliased, not 178 // hinted, this is very import for quality. (This is not possible with 179 // baked fonts.) 180 // 181 // - Kerning is now supported, and if you're supporting subpixel rendering 182 // then kerning is worth using to give your text a polished look. 183 // 184 // Performance: 185 // 186 // - Convert Unicode codepoints to glyph indexes and operate on the glyphs; 187 // if you don't do this, stb_truetype is forced to do the conversion on 188 // every call. 189 // 190 // - There are a lot of memory allocations. We should modify it to take 191 // a temp buffer and allocate from the temp buffer (without freeing), 192 // should help performance a lot. 193 // 194 // NOTES 195 // 196 // The system uses the raw data found in the .ttf file without changing it 197 // and without building auxiliary data structures. This is a bit inefficient 198 // on little-endian systems (the data is big-endian), but assuming you're 199 // caching the bitmaps or glyph shapes this shouldn't be a big deal. 200 // 201 // It appears to be very hard to programmatically determine what font a 202 // given file is in a general way. I provide an API for this, but I don't 203 // recommend it. 204 // 205 // 206 // SOURCE STATISTICS (based on v0.6c, 2050 LOC) 207 // 208 // Documentation & header file 520 LOC \___ 660 LOC documentation 209 // Sample code 140 LOC / 210 // Truetype parsing 620 LOC ---- 620 LOC TrueType 211 // Software rasterization 240 LOC \ . 212 // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation 213 // Bitmap management 100 LOC / 214 // Baked bitmap interface 70 LOC / 215 // Font name matching & access 150 LOC ---- 150 216 // C runtime library abstraction 60 LOC ---- 60 217 // 218 // 219 // PERFORMANCE MEASUREMENTS FOR 1.06: 220 // 221 // 32-bit 64-bit 222 // Previous release: 8.83 s 7.68 s 223 // Pool allocations: 7.72 s 6.34 s 224 // Inline sort : 6.54 s 5.65 s 225 // New rasterizer : 5.63 s 5.00 s 226 227 ////////////////////////////////////////////////////////////////////////////// 228 ////////////////////////////////////////////////////////////////////////////// 229 //// 230 //// SAMPLE PROGRAMS 231 //// 232 // 233 // Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless 234 // 235 #if 0 236 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation 237 #include "stb_truetype.h" 238 239 unsigned char ttf_buffer[1<<20]; 240 unsigned char temp_bitmap[512*512]; 241 242 stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs 243 GLuint ftex; 244 245 void my_stbtt_initfont(void) 246 { 247 fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); 248 stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits! 249 // can free ttf_buffer at this point 250 glGenTextures(1, &ftex); 251 glBindTexture(GL_TEXTURE_2D, ftex); 252 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); 253 // can free temp_bitmap at this point 254 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 255 } 256 257 void my_stbtt_print(float x, float y, char *text) 258 { 259 // assume orthographic projection with units = screen pixels, origin at top left 260 glEnable(GL_TEXTURE_2D); 261 glBindTexture(GL_TEXTURE_2D, ftex); 262 glBegin(GL_QUADS); 263 while (*text) { 264 if (*text >= 32 && *text < 128) { 265 stbtt_aligned_quad q; 266 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 267 glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); 268 glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); 269 glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); 270 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); 271 } 272 ++text; 273 } 274 glEnd(); 275 } 276 #endif 277 // 278 // 279 ////////////////////////////////////////////////////////////////////////////// 280 // 281 // Complete program (this compiles): get a single bitmap, print as ASCII art 282 // 283 #if 0 284 #include <stdio.h> 285 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation 286 #include "stb_truetype.h" 287 288 char ttf_buffer[1<<25]; 289 290 int main(int argc, char **argv) 291 { 292 stbtt_fontinfo font; 293 unsigned char *bitmap; 294 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); 295 296 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); 297 298 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); 299 bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); 300 301 for (j=0; j < h; ++j) { 302 for (i=0; i < w; ++i) 303 putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); 304 putchar('\n'); 305 } 306 return 0; 307 } 308 #endif 309 // 310 // Output: 311 // 312 // .ii. 313 // @@@@@@. 314 // V@Mio@@o 315 // :i. V@V 316 // :oM@@M 317 // :@@@MM@M 318 // @@o o@M 319 // :@@. M@M 320 // @@@o@@@@ 321 // :M@@V:@@. 322 // 323 ////////////////////////////////////////////////////////////////////////////// 324 // 325 // Complete program: print "Hello World!" banner, with bugs 326 // 327 #if 0 328 char buffer[24<<20]; 329 unsigned char screen[20][79]; 330 331 int main(int arg, char **argv) 332 { 333 stbtt_fontinfo font; 334 int i,j,ascent,baseline,ch=0; 335 float scale, xpos=2; // leave a little padding in case the character extends left 336 char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness 337 338 fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); 339 stbtt_InitFont(&font, buffer, 0); 340 341 scale = stbtt_ScaleForPixelHeight(&font, 15); 342 stbtt_GetFontVMetrics(&font, &ascent,0,0); 343 baseline = (int) (ascent*scale); 344 345 while (text[ch]) { 346 int advance,lsb,x0,y0,x1,y1; 347 float x_shift = xpos - (float) floor(xpos); 348 stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); 349 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); 350 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); 351 // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong 352 // because this API is really for baking character bitmaps into textures. if you want to render 353 // a sequence of characters, you really need to render each bitmap to a temp buffer, then 354 // "alpha blend" that into the working buffer 355 xpos += (advance * scale); 356 if (text[ch+1]) 357 xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); 358 ++ch; 359 } 360 361 for (j=0; j < 20; ++j) { 362 for (i=0; i < 78; ++i) 363 putchar(" .:ioVM@"[screen[j][i]>>5]); 364 putchar('\n'); 365 } 366 367 return 0; 368 } 369 #endif 370 371 372 ////////////////////////////////////////////////////////////////////////////// 373 ////////////////////////////////////////////////////////////////////////////// 374 //// 375 //// INTEGRATION WITH YOUR CODEBASE 376 //// 377 //// The following sections allow you to supply alternate definitions 378 //// of C library functions used by stb_truetype. 379 380 #ifdef STB_TRUETYPE_IMPLEMENTATION 381 // #define your own (u)stbtt_int8/16/32 before including to override this 382 #ifndef stbtt_uint8 383 typedef unsigned char stbtt_uint8; 384 typedef signed char stbtt_int8; 385 typedef unsigned short stbtt_uint16; 386 typedef signed short stbtt_int16; 387 typedef unsigned int stbtt_uint32; 388 typedef signed int stbtt_int32; 389 #endif 390 391 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; 392 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; 393 394 // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h 395 #ifndef STBTT_ifloor 396 #include <math.h> 397 #define STBTT_ifloor(x) ((int) floor(x)) 398 #define STBTT_iceil(x) ((int) ceil(x)) 399 #endif 400 401 #ifndef STBTT_sqrt 402 #include <math.h> 403 #define STBTT_sqrt(x) sqrt(x) 404 #endif 405 406 #ifndef STBTT_fabs 407 #include <math.h> 408 #define STBTT_fabs(x) fabs(x) 409 #endif 410 411 // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h 412 #ifndef STBTT_malloc 413 #include <stdlib.h> 414 #define STBTT_malloc(x,u) ((void)(u),malloc(x)) 415 #define STBTT_free(x,u) ((void)(u),free(x)) 416 #endif 417 418 #ifndef STBTT_assert 419 #include <assert.h> 420 #define STBTT_assert(x) assert(x) 421 #endif 422 423 #ifndef STBTT_strlen 424 #include <string.h> 425 #define STBTT_strlen(x) strlen(x) 426 #endif 427 428 #ifndef STBTT_memcpy 429 #include <memory.h> 430 #define STBTT_memcpy memcpy 431 #define STBTT_memset memset 432 #endif 433 #endif 434 435 /////////////////////////////////////////////////////////////////////////////// 436 /////////////////////////////////////////////////////////////////////////////// 437 //// 438 //// INTERFACE 439 //// 440 //// 441 442 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__ 443 #define __STB_INCLUDE_STB_TRUETYPE_H__ 444 445 #ifdef STBTT_STATIC 446 #define STBTT_DEF static 447 #else 448 #define STBTT_DEF extern 449 #endif 450 451 #ifdef __cplusplus 452 extern "C" { 453 #endif 454 455 ////////////////////////////////////////////////////////////////////////////// 456 // 457 // TEXTURE BAKING API 458 // 459 // If you use this API, you only have to call two functions ever. 460 // 461 462 typedef struct 463 { 464 unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap 465 float xoff,yoff,xadvance; 466 } stbtt_bakedchar; 467 468 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) 469 float pixel_height, // height of font in pixels 470 unsigned char *pixels, int pw, int ph, // bitmap to be filled in 471 int first_char, int num_chars, // characters to bake 472 stbtt_bakedchar *chardata); // you allocate this, it's num_chars long 473 // if return is positive, the first unused row of the bitmap 474 // if return is negative, returns the negative of the number of characters that fit 475 // if return is 0, no characters fit and no rows were used 476 // This uses a very crappy packing. 477 478 typedef struct 479 { 480 float x0,y0,s0,t0; // top-left 481 float x1,y1,s1,t1; // bottom-right 482 } stbtt_aligned_quad; 483 484 STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above 485 int char_index, // character to display 486 float *xpos, float *ypos, // pointers to current position in screen pixel space 487 stbtt_aligned_quad *q, // output: quad to draw 488 int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier 489 // Call GetBakedQuad with char_index = 'character - first_char', and it 490 // creates the quad you need to draw and advances the current position. 491 // 492 // The coordinate system used assumes y increases downwards. 493 // 494 // Characters will extend both above and below the current position; 495 // see discussion of "BASELINE" above. 496 // 497 // It's inefficient; you might want to c&p it and optimize it. 498 499 500 501 ////////////////////////////////////////////////////////////////////////////// 502 // 503 // NEW TEXTURE BAKING API 504 // 505 // This provides options for packing multiple fonts into one atlas, not 506 // perfectly but better than nothing. 507 508 typedef struct 509 { 510 unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap 511 float xoff,yoff,xadvance; 512 float xoff2,yoff2; 513 } stbtt_packedchar; 514 515 typedef struct stbtt_pack_context stbtt_pack_context; 516 typedef struct stbtt_fontinfo stbtt_fontinfo; 517 #ifndef STB_RECT_PACK_VERSION 518 typedef struct stbrp_rect stbrp_rect; 519 #endif 520 521 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); 522 // Initializes a packing context stored in the passed-in stbtt_pack_context. 523 // Future calls using this context will pack characters into the bitmap passed 524 // in here: a 1-channel bitmap that is weight x height. stride_in_bytes is 525 // the distance from one row to the next (or 0 to mean they are packed tightly 526 // together). "padding" is the amount of padding to leave between each 527 // character (normally you want '1' for bitmaps you'll use as textures with 528 // bilinear filtering). 529 // 530 // Returns 0 on failure, 1 on success. 531 532 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); 533 // Cleans up the packing context and frees all memory. 534 535 #define STBTT_POINT_SIZE(x) (-(x)) 536 537 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, 538 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); 539 // Creates character bitmaps from the font_index'th font found in fontdata (use 540 // font_index=0 if you don't know what that is). It creates num_chars_in_range 541 // bitmaps for characters with unicode values starting at first_unicode_char_in_range 542 // and increasing. Data for how to render them is stored in chardata_for_range; 543 // pass these to stbtt_GetPackedQuad to get back renderable quads. 544 // 545 // font_size is the full height of the character from ascender to descender, 546 // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed 547 // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() 548 // and pass that result as 'font_size': 549 // ..., 20 , ... // font max minus min y is 20 pixels tall 550 // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall 551 552 typedef struct 553 { 554 float font_size; 555 int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint 556 int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints 557 int num_chars; 558 stbtt_packedchar *chardata_for_range; // output 559 unsigned char h_oversample, v_oversample; // don't set these, they're used internally 560 } stbtt_pack_range; 561 562 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); 563 // Creates character bitmaps from multiple ranges of characters stored in 564 // ranges. This will usually create a better-packed bitmap than multiple 565 // calls to stbtt_PackFontRange. Note that you can call this multiple 566 // times within a single PackBegin/PackEnd. 567 568 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); 569 // Oversampling a font increases the quality by allowing higher-quality subpixel 570 // positioning, and is especially valuable at smaller text sizes. 571 // 572 // This function sets the amount of oversampling for all following calls to 573 // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given 574 // pack context. The default (no oversampling) is achieved by h_oversample=1 575 // and v_oversample=1. The total number of pixels required is 576 // h_oversample*v_oversample larger than the default; for example, 2x2 577 // oversampling requires 4x the storage of 1x1. For best results, render 578 // oversampled textures with bilinear filtering. Look at the readme in 579 // stb/tests/oversample for information about oversampled fonts 580 // 581 // To use with PackFontRangesGather etc., you must set it before calls 582 // call to PackFontRangesGatherRects. 583 584 STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above 585 int char_index, // character to display 586 float *xpos, float *ypos, // pointers to current position in screen pixel space 587 stbtt_aligned_quad *q, // output: quad to draw 588 int align_to_integer); 589 590 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 591 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); 592 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 593 // Calling these functions in sequence is roughly equivalent to calling 594 // stbtt_PackFontRanges(). If you more control over the packing of multiple 595 // fonts, or if you want to pack custom data into a font texture, take a look 596 // at the source to of stbtt_PackFontRanges() and create a custom version 597 // using these functions, e.g. call GatherRects multiple times, 598 // building up a single array of rects, then call PackRects once, 599 // then call RenderIntoRects repeatedly. This may result in a 600 // better packing than calling PackFontRanges multiple times 601 // (or it may not). 602 603 // this is an opaque structure that you shouldn't mess with which holds 604 // all the context needed from PackBegin to PackEnd. 605 struct stbtt_pack_context { 606 void *user_allocator_context; 607 void *pack_info; 608 int width; 609 int height; 610 int stride_in_bytes; 611 int padding; 612 unsigned int h_oversample, v_oversample; 613 unsigned char *pixels; 614 void *nodes; 615 }; 616 617 ////////////////////////////////////////////////////////////////////////////// 618 // 619 // FONT LOADING 620 // 621 // 622 623 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); 624 // Each .ttf/.ttc file may have more than one font. Each font has a sequential 625 // index number starting from 0. Call this function to get the font offset for 626 // a given index; it returns -1 if the index is out of range. A regular .ttf 627 // file will only define one font and it always be at offset 0, so it will 628 // return '0' for index 0, and -1 for all other indices. You can just skip 629 // this step if you know it's that kind of font. 630 631 632 // The following structure is defined publically so you can declare one on 633 // the stack or as a global or etc, but you should treat it as opaque. 634 typedef struct stbtt_fontinfo 635 { 636 void * userdata; 637 unsigned char * data; // pointer to .ttf file 638 int fontstart; // offset of start of font 639 640 int numGlyphs; // number of glyphs, needed for range checking 641 642 int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf 643 int index_map; // a cmap mapping for our chosen character encoding 644 int indexToLocFormat; // format needed to map from glyph index to glyph 645 } stbtt_fontinfo; 646 647 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); 648 // Given an offset into the file that defines a font, this function builds 649 // the necessary cached info for the rest of the system. You must allocate 650 // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't 651 // need to do anything special to free it, because the contents are pure 652 // value data with no additional data structures. Returns 0 on failure. 653 654 655 ////////////////////////////////////////////////////////////////////////////// 656 // 657 // CHARACTER TO GLYPH-INDEX CONVERSIOn 658 659 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); 660 // If you're going to perform multiple operations on the same character 661 // and you want a speed-up, call this function with the character you're 662 // going to process, then use glyph-based functions instead of the 663 // codepoint-based functions. 664 665 666 ////////////////////////////////////////////////////////////////////////////// 667 // 668 // CHARACTER PROPERTIES 669 // 670 671 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); 672 // computes a scale factor to produce a font whose "height" is 'pixels' tall. 673 // Height is measured as the distance from the highest ascender to the lowest 674 // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics 675 // and computing: 676 // scale = pixels / (ascent - descent) 677 // so if you prefer to measure height by the ascent only, use a similar calculation. 678 679 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); 680 // computes a scale factor to produce a font whose EM size is mapped to 681 // 'pixels' tall. This is probably what traditional APIs compute, but 682 // I'm not positive. 683 684 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); 685 // ascent is the coordinate above the baseline the font extends; descent 686 // is the coordinate below the baseline the font extends (i.e. it is typically negative) 687 // lineGap is the spacing between one row's descent and the next row's ascent... 688 // so you should advance the vertical position by "*ascent - *descent + *lineGap" 689 // these are expressed in unscaled coordinates, so you must multiply by 690 // the scale factor for a given size 691 692 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); 693 // the bounding box around all possible characters 694 695 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); 696 // leftSideBearing is the offset from the current horizontal position to the left edge of the character 697 // advanceWidth is the offset from the current horizontal position to the next horizontal position 698 // these are expressed in unscaled coordinates 699 700 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); 701 // an additional amount to add to the 'advance' value between ch1 and ch2 702 703 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); 704 // Gets the bounding box of the visible part of the glyph, in unscaled coordinates 705 706 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); 707 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); 708 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); 709 // as above, but takes one or more glyph indices for greater efficiency 710 711 712 ////////////////////////////////////////////////////////////////////////////// 713 // 714 // GLYPH SHAPES (you probably don't need these, but they have to go before 715 // the bitmaps for C declaration-order reasons) 716 // 717 718 #ifndef STBTT_vmove // you can predefine these to use different values (but why?) 719 enum { 720 STBTT_vmove=1, 721 STBTT_vline, 722 STBTT_vcurve 723 }; 724 #endif 725 726 #ifndef stbtt_vertex // you can predefine this to use different values 727 // (we share this with other code at RAD) 728 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file 729 typedef struct 730 { 731 stbtt_vertex_type x,y,cx,cy; 732 unsigned char type,padding; 733 } stbtt_vertex; 734 #endif 735 736 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); 737 // returns non-zero if nothing is drawn for this glyph 738 739 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); 740 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); 741 // returns # of vertices and fills *vertices with the pointer to them 742 // these are expressed in "unscaled" coordinates 743 // 744 // The shape is a series of countours. Each one starts with 745 // a STBTT_moveto, then consists of a series of mixed 746 // STBTT_lineto and STBTT_curveto segments. A lineto 747 // draws a line from previous endpoint to its x,y; a curveto 748 // draws a quadratic bezier from previous endpoint to 749 // its x,y, using cx,cy as the bezier control point. 750 751 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); 752 // frees the data allocated above 753 754 ////////////////////////////////////////////////////////////////////////////// 755 // 756 // BITMAP RENDERING 757 // 758 759 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); 760 // frees the bitmap allocated below 761 762 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); 763 // allocates a large-enough single-channel 8bpp bitmap and renders the 764 // specified character/glyph at the specified scale into it, with 765 // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). 766 // *width & *height are filled out with the width & height of the bitmap, 767 // which is stored left-to-right, top-to-bottom. 768 // 769 // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap 770 771 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); 772 // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel 773 // shift for the character 774 775 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); 776 // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap 777 // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap 778 // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the 779 // width and height and positioning info for it first. 780 781 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); 782 // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel 783 // shift for the character 784 785 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); 786 // get the bbox of the bitmap centered around the glyph origin; so the 787 // bitmap width is ix1-ix0, height is iy1-iy0, and location to place 788 // the bitmap top left is (leftSideBearing*scale,iy0). 789 // (Note that the bitmap uses y-increases-down, but the shape uses 790 // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) 791 792 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); 793 // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel 794 // shift for the character 795 796 // the following functions are equivalent to the above functions, but operate 797 // on glyph indices instead of Unicode codepoints (for efficiency) 798 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); 799 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); 800 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); 801 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); 802 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); 803 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 805 806 // @TODO: don't expose this structure 807 typedef struct 808 { 809 int w,h,stride; 810 unsigned char *pixels; 811 } stbtt__bitmap; 812 813 // rasterize a shape with quadratic beziers into a bitmap 814 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into 815 float flatness_in_pixels, // allowable error of curve in pixels 816 stbtt_vertex *vertices, // array of vertices defining shape 817 int num_verts, // number of vertices in above array 818 float scale_x, float scale_y, // scale applied to input vertices 819 float shift_x, float shift_y, // translation applied to input vertices 820 int x_off, int y_off, // another translation applied to input 821 int invert, // if non-zero, vertically flip shape 822 void *userdata); // context for to STBTT_MALLOC 823 824 ////////////////////////////////////////////////////////////////////////////// 825 // 826 // Finding the right font... 827 // 828 // You should really just solve this offline, keep your own tables 829 // of what font is what, and don't try to get it out of the .ttf file. 830 // That's because getting it out of the .ttf file is really hard, because 831 // the names in the file can appear in many possible encodings, in many 832 // possible languages, and e.g. if you need a case-insensitive comparison, 833 // the details of that depend on the encoding & language in a complex way 834 // (actually underspecified in truetype, but also gigantic). 835 // 836 // But you can use the provided functions in two possible ways: 837 // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on 838 // unicode-encoded names to try to find the font you want; 839 // you can run this before calling stbtt_InitFont() 840 // 841 // stbtt_GetFontNameString() lets you get any of the various strings 842 // from the file yourself and do your own comparisons on them. 843 // You have to have called stbtt_InitFont() first. 844 845 846 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); 847 // returns the offset (not index) of the font that matches, or -1 if none 848 // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". 849 // if you use any other flag, use a font name like "Arial"; this checks 850 // the 'macStyle' header field; i don't know if fonts set this consistently 851 #define STBTT_MACSTYLE_DONTCARE 0 852 #define STBTT_MACSTYLE_BOLD 1 853 #define STBTT_MACSTYLE_ITALIC 2 854 #define STBTT_MACSTYLE_UNDERSCORE 4 855 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 856 857 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); 858 // returns 1/0 whether the first string interpreted as utf8 is identical to 859 // the second string interpreted as big-endian utf16... useful for strings from next func 860 861 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); 862 // returns the string (which may be big-endian double byte, e.g. for unicode) 863 // and puts the length in bytes in *length. 864 // 865 // some of the values for the IDs are below; for more see the truetype spec: 866 // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html 867 // http://www.microsoft.com/typography/otspec/name.htm 868 869 enum { // platformID 870 STBTT_PLATFORM_ID_UNICODE =0, 871 STBTT_PLATFORM_ID_MAC =1, 872 STBTT_PLATFORM_ID_ISO =2, 873 STBTT_PLATFORM_ID_MICROSOFT =3 874 }; 875 876 enum { // encodingID for STBTT_PLATFORM_ID_UNICODE 877 STBTT_UNICODE_EID_UNICODE_1_0 =0, 878 STBTT_UNICODE_EID_UNICODE_1_1 =1, 879 STBTT_UNICODE_EID_ISO_10646 =2, 880 STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, 881 STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 882 }; 883 884 enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT 885 STBTT_MS_EID_SYMBOL =0, 886 STBTT_MS_EID_UNICODE_BMP =1, 887 STBTT_MS_EID_SHIFTJIS =2, 888 STBTT_MS_EID_UNICODE_FULL =10 889 }; 890 891 enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes 892 STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, 893 STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, 894 STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, 895 STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 896 }; 897 898 enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... 899 // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs 900 STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, 901 STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, 902 STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, 903 STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, 904 STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, 905 STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D 906 }; 907 908 enum { // languageID for STBTT_PLATFORM_ID_MAC 909 STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, 910 STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, 911 STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, 912 STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , 913 STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , 914 STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, 915 STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 916 }; 917 918 #ifdef __cplusplus 919 } 920 #endif 921 922 #endif // __STB_INCLUDE_STB_TRUETYPE_H__ 923 924 /////////////////////////////////////////////////////////////////////////////// 925 /////////////////////////////////////////////////////////////////////////////// 926 //// 927 //// IMPLEMENTATION 928 //// 929 //// 930 931 #ifdef STB_TRUETYPE_IMPLEMENTATION 932 933 #ifndef STBTT_MAX_OVERSAMPLE 934 #define STBTT_MAX_OVERSAMPLE 8 935 #endif 936 937 #if STBTT_MAX_OVERSAMPLE > 255 938 #error "STBTT_MAX_OVERSAMPLE cannot be > 255" 939 #endif 940 941 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; 942 943 #ifndef STBTT_RASTERIZER_VERSION 944 #define STBTT_RASTERIZER_VERSION 2 945 #endif 946 947 ////////////////////////////////////////////////////////////////////////// 948 // 949 // accessors to parse data from file 950 // 951 952 // on platforms that don't allow misaligned reads, if we want to allow 953 // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE 954 955 #define ttBYTE(p) (* (stbtt_uint8 *) (p)) 956 #define ttCHAR(p) (* (stbtt_int8 *) (p)) 957 #define ttFixed(p) ttLONG(p) 958 959 #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) 960 961 #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) 962 #define ttSHORT(p) (* (stbtt_int16 *) (p)) 963 #define ttULONG(p) (* (stbtt_uint32 *) (p)) 964 #define ttLONG(p) (* (stbtt_int32 *) (p)) 965 966 #else 967 968 static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } 969 static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } 970 static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } 971 static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } 972 973 #endif 974 975 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) 976 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) 977 978 static int stbtt__isfont(const stbtt_uint8 *font) 979 { 980 // check the version number 981 if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 982 if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! 983 if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF 984 if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 985 return 0; 986 } 987 988 // @OPTIMIZE: binary search 989 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) 990 { 991 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); 992 stbtt_uint32 tabledir = fontstart + 12; 993 stbtt_int32 i; 994 for (i=0; i < num_tables; ++i) { 995 stbtt_uint32 loc = tabledir + 16*i; 996 if (stbtt_tag(data+loc+0, tag)) 997 return ttULONG(data+loc+8); 998 } 999 return 0; 1000 } 1001 1002 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) 1003 { 1004 // if it's just a font, there's only one valid index 1005 if (stbtt__isfont(font_collection)) 1006 return index == 0 ? 0 : -1; 1007 1008 // check if it's a TTC 1009 if (stbtt_tag(font_collection, "ttcf")) { 1010 // version 1? 1011 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { 1012 stbtt_int32 n = ttLONG(font_collection+8); 1013 if (index >= n) 1014 return -1; 1015 return ttULONG(font_collection+12+index*4); 1016 } 1017 } 1018 return -1; 1019 } 1020 1021 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) 1022 { 1023 stbtt_uint8 *data = (stbtt_uint8 *) data2; 1024 stbtt_uint32 cmap, t; 1025 stbtt_int32 i,numTables; 1026 1027 info->data = data; 1028 info->fontstart = fontstart; 1029 1030 cmap = stbtt__find_table(data, fontstart, "cmap"); // required 1031 info->loca = stbtt__find_table(data, fontstart, "loca"); // required 1032 info->head = stbtt__find_table(data, fontstart, "head"); // required 1033 info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required 1034 info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required 1035 info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required 1036 info->kern = stbtt__find_table(data, fontstart, "kern"); // not required 1037 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) 1038 return 0; 1039 1040 t = stbtt__find_table(data, fontstart, "maxp"); 1041 if (t) 1042 info->numGlyphs = ttUSHORT(data+t+4); 1043 else 1044 info->numGlyphs = 0xffff; 1045 1046 // find a cmap encoding table we understand *now* to avoid searching 1047 // later. (todo: could make this installable) 1048 // the same regardless of glyph. 1049 numTables = ttUSHORT(data + cmap + 2); 1050 info->index_map = 0; 1051 for (i=0; i < numTables; ++i) { 1052 stbtt_uint32 encoding_record = cmap + 4 + 8 * i; 1053 // find an encoding we understand: 1054 switch(ttUSHORT(data+encoding_record)) { 1055 case STBTT_PLATFORM_ID_MICROSOFT: 1056 switch (ttUSHORT(data+encoding_record+2)) { 1057 case STBTT_MS_EID_UNICODE_BMP: 1058 case STBTT_MS_EID_UNICODE_FULL: 1059 // MS/Unicode 1060 info->index_map = cmap + ttULONG(data+encoding_record+4); 1061 break; 1062 } 1063 break; 1064 case STBTT_PLATFORM_ID_UNICODE: 1065 // Mac/iOS has these 1066 // all the encodingIDs are unicode, so we don't bother to check it 1067 info->index_map = cmap + ttULONG(data+encoding_record+4); 1068 break; 1069 } 1070 } 1071 if (info->index_map == 0) 1072 return 0; 1073 1074 info->indexToLocFormat = ttUSHORT(data+info->head + 50); 1075 return 1; 1076 } 1077 1078 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) 1079 { 1080 stbtt_uint8 *data = info->data; 1081 stbtt_uint32 index_map = info->index_map; 1082 1083 stbtt_uint16 format = ttUSHORT(data + index_map + 0); 1084 if (format == 0) { // apple byte encoding 1085 stbtt_int32 bytes = ttUSHORT(data + index_map + 2); 1086 if (unicode_codepoint < bytes-6) 1087 return ttBYTE(data + index_map + 6 + unicode_codepoint); 1088 return 0; 1089 } else if (format == 6) { 1090 stbtt_uint32 first = ttUSHORT(data + index_map + 6); 1091 stbtt_uint32 count = ttUSHORT(data + index_map + 8); 1092 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) 1093 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); 1094 return 0; 1095 } else if (format == 2) { 1096 STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean 1097 return 0; 1098 } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges 1099 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; 1100 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; 1101 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); 1102 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; 1103 1104 // do a binary search of the segments 1105 stbtt_uint32 endCount = index_map + 14; 1106 stbtt_uint32 search = endCount; 1107 1108 if (unicode_codepoint > 0xffff) 1109 return 0; 1110 1111 // they lie from endCount .. endCount + segCount 1112 // but searchRange is the nearest power of two, so... 1113 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) 1114 search += rangeShift*2; 1115 1116 // now decrement to bias correctly to find smallest 1117 search -= 2; 1118 while (entrySelector) { 1119 stbtt_uint16 end; 1120 searchRange >>= 1; 1121 end = ttUSHORT(data + search + searchRange*2); 1122 if (unicode_codepoint > end) 1123 search += searchRange*2; 1124 --entrySelector; 1125 } 1126 search += 2; 1127 1128 { 1129 stbtt_uint16 offset, start; 1130 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); 1131 1132 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); 1133 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); 1134 if (unicode_codepoint < start) 1135 return 0; 1136 1137 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); 1138 if (offset == 0) 1139 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); 1140 1141 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); 1142 } 1143 } else if (format == 12 || format == 13) { 1144 stbtt_uint32 ngroups = ttULONG(data+index_map+12); 1145 stbtt_int32 low,high; 1146 low = 0; high = (stbtt_int32)ngroups; 1147 // Binary search the right group. 1148 while (low < high) { 1149 stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high 1150 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); 1151 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); 1152 if ((stbtt_uint32) unicode_codepoint < start_char) 1153 high = mid; 1154 else if ((stbtt_uint32) unicode_codepoint > end_char) 1155 low = mid+1; 1156 else { 1157 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); 1158 if (format == 12) 1159 return start_glyph + unicode_codepoint-start_char; 1160 else // format == 13 1161 return start_glyph; 1162 } 1163 } 1164 return 0; // not found 1165 } 1166 // @TODO 1167 STBTT_assert(0); 1168 return 0; 1169 } 1170 1171 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) 1172 { 1173 return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); 1174 } 1175 1176 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) 1177 { 1178 v->type = type; 1179 v->x = (stbtt_int16) x; 1180 v->y = (stbtt_int16) y; 1181 v->cx = (stbtt_int16) cx; 1182 v->cy = (stbtt_int16) cy; 1183 } 1184 1185 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) 1186 { 1187 int g1,g2; 1188 1189 if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range 1190 if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format 1191 1192 if (info->indexToLocFormat == 0) { 1193 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; 1194 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; 1195 } else { 1196 g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); 1197 g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); 1198 } 1199 1200 return g1==g2 ? -1 : g1; // if length is 0, return -1 1201 } 1202 1203 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) 1204 { 1205 int g = stbtt__GetGlyfOffset(info, glyph_index); 1206 if (g < 0) return 0; 1207 1208 if (x0) *x0 = ttSHORT(info->data + g + 2); 1209 if (y0) *y0 = ttSHORT(info->data + g + 4); 1210 if (x1) *x1 = ttSHORT(info->data + g + 6); 1211 if (y1) *y1 = ttSHORT(info->data + g + 8); 1212 return 1; 1213 } 1214 1215 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) 1216 { 1217 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); 1218 } 1219 1220 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) 1221 { 1222 stbtt_int16 numberOfContours; 1223 int g = stbtt__GetGlyfOffset(info, glyph_index); 1224 if (g < 0) return 1; 1225 numberOfContours = ttSHORT(info->data + g); 1226 return numberOfContours == 0; 1227 } 1228 1229 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, 1230 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) 1231 { 1232 if (start_off) { 1233 if (was_off) 1234 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); 1235 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); 1236 } else { 1237 if (was_off) 1238 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); 1239 else 1240 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); 1241 } 1242 return num_vertices; 1243 } 1244 1245 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) 1246 { 1247 stbtt_int16 numberOfContours; 1248 stbtt_uint8 *endPtsOfContours; 1249 stbtt_uint8 *data = info->data; 1250 stbtt_vertex *vertices=0; 1251 int num_vertices=0; 1252 int g = stbtt__GetGlyfOffset(info, glyph_index); 1253 1254 *pvertices = NULL; 1255 1256 if (g < 0) return 0; 1257 1258 numberOfContours = ttSHORT(data + g); 1259 1260 if (numberOfContours > 0) { 1261 stbtt_uint8 flags=0,flagcount; 1262 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; 1263 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; 1264 stbtt_uint8 *points; 1265 endPtsOfContours = (data + g + 10); 1266 ins = ttUSHORT(data + g + 10 + numberOfContours * 2); 1267 points = data + g + 10 + numberOfContours * 2 + 2 + ins; 1268 1269 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); 1270 1271 m = n + 2*numberOfContours; // a loose bound on how many vertices we might need 1272 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); 1273 if (vertices == 0) 1274 return 0; 1275 1276 next_move = 0; 1277 flagcount=0; 1278 1279 // in first pass, we load uninterpreted data into the allocated array 1280 // above, shifted to the end of the array so we won't overwrite it when 1281 // we create our final data starting from the front 1282 1283 off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated 1284 1285 // first load flags 1286 1287 for (i=0; i < n; ++i) { 1288 if (flagcount == 0) { 1289 flags = *points++; 1290 if (flags & 8) 1291 flagcount = *points++; 1292 } else 1293 --flagcount; 1294 vertices[off+i].type = flags; 1295 } 1296 1297 // now load x coordinates 1298 x=0; 1299 for (i=0; i < n; ++i) { 1300 flags = vertices[off+i].type; 1301 if (flags & 2) { 1302 stbtt_int16 dx = *points++; 1303 x += (flags & 16) ? dx : -dx; // ??? 1304 } else { 1305 if (!(flags & 16)) { 1306 x = x + (stbtt_int16) (points[0]*256 + points[1]); 1307 points += 2; 1308 } 1309 } 1310 vertices[off+i].x = (stbtt_int16) x; 1311 } 1312 1313 // now load y coordinates 1314 y=0; 1315 for (i=0; i < n; ++i) { 1316 flags = vertices[off+i].type; 1317 if (flags & 4) { 1318 stbtt_int16 dy = *points++; 1319 y += (flags & 32) ? dy : -dy; // ??? 1320 } else { 1321 if (!(flags & 32)) { 1322 y = y + (stbtt_int16) (points[0]*256 + points[1]); 1323 points += 2; 1324 } 1325 } 1326 vertices[off+i].y = (stbtt_int16) y; 1327 } 1328 1329 // now convert them to our format 1330 num_vertices=0; 1331 sx = sy = cx = cy = scx = scy = 0; 1332 for (i=0; i < n; ++i) { 1333 flags = vertices[off+i].type; 1334 x = (stbtt_int16) vertices[off+i].x; 1335 y = (stbtt_int16) vertices[off+i].y; 1336 1337 if (next_move == i) { 1338 if (i != 0) 1339 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 1340 1341 // now start the new one 1342 start_off = !(flags & 1); 1343 if (start_off) { 1344 // if we start off with an off-curve point, then when we need to find a point on the curve 1345 // where we can start, and we need to save some state for when we wraparound. 1346 scx = x; 1347 scy = y; 1348 if (!(vertices[off+i+1].type & 1)) { 1349 // next point is also a curve point, so interpolate an on-point curve 1350 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; 1351 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; 1352 } else { 1353 // otherwise just use the next point as our start point 1354 sx = (stbtt_int32) vertices[off+i+1].x; 1355 sy = (stbtt_int32) vertices[off+i+1].y; 1356 ++i; // we're using point i+1 as the starting point, so skip it 1357 } 1358 } else { 1359 sx = x; 1360 sy = y; 1361 } 1362 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); 1363 was_off = 0; 1364 next_move = 1 + ttUSHORT(endPtsOfContours+j*2); 1365 ++j; 1366 } else { 1367 if (!(flags & 1)) { // if it's a curve 1368 if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint 1369 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); 1370 cx = x; 1371 cy = y; 1372 was_off = 1; 1373 } else { 1374 if (was_off) 1375 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); 1376 else 1377 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); 1378 was_off = 0; 1379 } 1380 } 1381 } 1382 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 1383 } else if (numberOfContours == -1) { 1384 // Compound shapes. 1385 int more = 1; 1386 stbtt_uint8 *comp = data + g + 10; 1387 num_vertices = 0; 1388 vertices = 0; 1389 while (more) { 1390 stbtt_uint16 flags, gidx; 1391 int comp_num_verts = 0, i; 1392 stbtt_vertex *comp_verts = 0, *tmp = 0; 1393 float mtx[6] = {1,0,0,1,0,0}, m, n; 1394 1395 flags = ttSHORT(comp); comp+=2; 1396 gidx = ttSHORT(comp); comp+=2; 1397 1398 if (flags & 2) { // XY values 1399 if (flags & 1) { // shorts 1400 mtx[4] = ttSHORT(comp); comp+=2; 1401 mtx[5] = ttSHORT(comp); comp+=2; 1402 } else { 1403 mtx[4] = ttCHAR(comp); comp+=1; 1404 mtx[5] = ttCHAR(comp); comp+=1; 1405 } 1406 } 1407 else { 1408 // @TODO handle matching point 1409 STBTT_assert(0); 1410 } 1411 if (flags & (1<<3)) { // WE_HAVE_A_SCALE 1412 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 1413 mtx[1] = mtx[2] = 0; 1414 } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE 1415 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; 1416 mtx[1] = mtx[2] = 0; 1417 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 1418 } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO 1419 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; 1420 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; 1421 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; 1422 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 1423 } 1424 1425 // Find transformation scales. 1426 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); 1427 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); 1428 1429 // Get indexed glyph. 1430 comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); 1431 if (comp_num_verts > 0) { 1432 // Transform vertices. 1433 for (i = 0; i < comp_num_verts; ++i) { 1434 stbtt_vertex* v = &comp_verts[i]; 1435 stbtt_vertex_type x,y; 1436 x=v->x; y=v->y; 1437 v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 1438 v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 1439 x=v->cx; y=v->cy; 1440 v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 1441 v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 1442 } 1443 // Append vertices. 1444 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); 1445 if (!tmp) { 1446 if (vertices) STBTT_free(vertices, info->userdata); 1447 if (comp_verts) STBTT_free(comp_verts, info->userdata); 1448 return 0; 1449 } 1450 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); 1451 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); 1452 if (vertices) STBTT_free(vertices, info->userdata); 1453 vertices = tmp; 1454 STBTT_free(comp_verts, info->userdata); 1455 num_vertices += comp_num_verts; 1456 } 1457 // More components ? 1458 more = flags & (1<<5); 1459 } 1460 } else if (numberOfContours < 0) { 1461 // @TODO other compound variations? 1462 STBTT_assert(0); 1463 } else { 1464 // numberOfCounters == 0, do nothing 1465 } 1466 1467 *pvertices = vertices; 1468 return num_vertices; 1469 } 1470 1471 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) 1472 { 1473 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); 1474 if (glyph_index < numOfLongHorMetrics) { 1475 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); 1476 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); 1477 } else { 1478 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); 1479 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); 1480 } 1481 } 1482 1483 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) 1484 { 1485 stbtt_uint8 *data = info->data + info->kern; 1486 stbtt_uint32 needle, straw; 1487 int l, r, m; 1488 1489 // we only look at the first table. it must be 'horizontal' and format 0. 1490 if (!info->kern) 1491 return 0; 1492 if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 1493 return 0; 1494 if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format 1495 return 0; 1496 1497 l = 0; 1498 r = ttUSHORT(data+10) - 1; 1499 needle = glyph1 << 16 | glyph2; 1500 while (l <= r) { 1501 m = (l + r) >> 1; 1502 straw = ttULONG(data+18+(m*6)); // note: unaligned read 1503 if (needle < straw) 1504 r = m - 1; 1505 else if (needle > straw) 1506 l = m + 1; 1507 else 1508 return ttSHORT(data+22+(m*6)); 1509 } 1510 return 0; 1511 } 1512 1513 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) 1514 { 1515 if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs 1516 return 0; 1517 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); 1518 } 1519 1520 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) 1521 { 1522 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); 1523 } 1524 1525 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) 1526 { 1527 if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); 1528 if (descent) *descent = ttSHORT(info->data+info->hhea + 6); 1529 if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); 1530 } 1531 1532 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) 1533 { 1534 *x0 = ttSHORT(info->data + info->head + 36); 1535 *y0 = ttSHORT(info->data + info->head + 38); 1536 *x1 = ttSHORT(info->data + info->head + 40); 1537 *y1 = ttSHORT(info->data + info->head + 42); 1538 } 1539 1540 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) 1541 { 1542 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); 1543 return (float) height / fheight; 1544 } 1545 1546 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) 1547 { 1548 int unitsPerEm = ttUSHORT(info->data + info->head + 18); 1549 return pixels / unitsPerEm; 1550 } 1551 1552 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) 1553 { 1554 STBTT_free(v, info->userdata); 1555 } 1556 1557 ////////////////////////////////////////////////////////////////////////////// 1558 // 1559 // antialiasing software rasterizer 1560 // 1561 1562 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) 1563 { 1564 int x0,y0,x1,y1; 1565 if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { 1566 // e.g. space character 1567 if (ix0) *ix0 = 0; 1568 if (iy0) *iy0 = 0; 1569 if (ix1) *ix1 = 0; 1570 if (iy1) *iy1 = 0; 1571 } else { 1572 // move to integral bboxes (treating pixels as little squares, what pixels get touched)? 1573 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); 1574 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); 1575 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); 1576 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); 1577 } 1578 } 1579 1580 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) 1581 { 1582 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); 1583 } 1584 1585 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) 1586 { 1587 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); 1588 } 1589 1590 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) 1591 { 1592 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); 1593 } 1594 1595 ////////////////////////////////////////////////////////////////////////////// 1596 // 1597 // Rasterizer 1598 1599 typedef struct stbtt__hheap_chunk 1600 { 1601 struct stbtt__hheap_chunk *next; 1602 } stbtt__hheap_chunk; 1603 1604 typedef struct stbtt__hheap 1605 { 1606 struct stbtt__hheap_chunk *head; 1607 void *first_free; 1608 int num_remaining_in_head_chunk; 1609 } stbtt__hheap; 1610 1611 static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) 1612 { 1613 if (hh->first_free) { 1614 void *p = hh->first_free; 1615 hh->first_free = * (void **) p; 1616 return p; 1617 } else { 1618 if (hh->num_remaining_in_head_chunk == 0) { 1619 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); 1620 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); 1621 if (c == NULL) 1622 return NULL; 1623 c->next = hh->head; 1624 hh->head = c; 1625 hh->num_remaining_in_head_chunk = count; 1626 } 1627 --hh->num_remaining_in_head_chunk; 1628 return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; 1629 } 1630 } 1631 1632 static void stbtt__hheap_free(stbtt__hheap *hh, void *p) 1633 { 1634 *(void **) p = hh->first_free; 1635 hh->first_free = p; 1636 } 1637 1638 static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) 1639 { 1640 stbtt__hheap_chunk *c = hh->head; 1641 while (c) { 1642 stbtt__hheap_chunk *n = c->next; 1643 STBTT_free(c, userdata); 1644 c = n; 1645 } 1646 } 1647 1648 typedef struct stbtt__edge { 1649 float x0,y0, x1,y1; 1650 int invert; 1651 } stbtt__edge; 1652 1653 1654 typedef struct stbtt__active_edge 1655 { 1656 struct stbtt__active_edge *next; 1657 #if STBTT_RASTERIZER_VERSION==1 1658 int x,dx; 1659 float ey; 1660 int direction; 1661 #elif STBTT_RASTERIZER_VERSION==2 1662 float fx,fdx,fdy; 1663 float direction; 1664 float sy; 1665 float ey; 1666 #else 1667 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 1668 #endif 1669 } stbtt__active_edge; 1670 1671 #if STBTT_RASTERIZER_VERSION == 1 1672 #define STBTT_FIXSHIFT 10 1673 #define STBTT_FIX (1 << STBTT_FIXSHIFT) 1674 #define STBTT_FIXMASK (STBTT_FIX-1) 1675 1676 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) 1677 { 1678 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); 1679 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 1680 if (!z) return z; 1681 1682 // round dx down to avoid overshooting 1683 if (dxdy < 0) 1684 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); 1685 else 1686 z->dx = STBTT_ifloor(STBTT_FIX * dxdy); 1687 1688 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 1689 z->x -= off_x * STBTT_FIX; 1690 1691 z->ey = e->y1; 1692 z->next = 0; 1693 z->direction = e->invert ? 1 : -1; 1694 return z; 1695 } 1696 #elif STBTT_RASTERIZER_VERSION == 2 1697 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) 1698 { 1699 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); 1700 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 1701 //STBTT_assert(e->y0 <= start_point); 1702 if (!z) return z; 1703 z->fdx = dxdy; 1704 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; 1705 z->fx = e->x0 + dxdy * (start_point - e->y0); 1706 z->fx -= off_x; 1707 z->direction = e->invert ? 1.0f : -1.0f; 1708 z->sy = e->y0; 1709 z->ey = e->y1; 1710 z->next = 0; 1711 return z; 1712 } 1713 #else 1714 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 1715 #endif 1716 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) 1722 { 1723 // non-zero winding fill 1724 int x0=0, w=0; 1725 1726 while (e) { 1727 if (w == 0) { 1728 // if we're currently at zero, we need to record the edge start point 1729 x0 = e->x; w += e->direction; 1730 } else { 1731 int x1 = e->x; w += e->direction; 1732 // if we went to zero, we need to draw 1733 if (w == 0) { 1734 int i = x0 >> STBTT_FIXSHIFT; 1735 int j = x1 >> STBTT_FIXSHIFT; 1736 1737 if (i < len && j >= 0) { 1738 if (i == j) { 1739 // x0,x1 are the same pixel, so compute combined coverage 1740 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); 1741 } else { 1742 if (i >= 0) // add antialiasing for x0 1743 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); 1744 else 1745 i = -1; // clip 1746 1747 if (j < len) // add antialiasing for x1 1748 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); 1749 else 1750 j = len; // clip 1751 1752 for (++i; i < j; ++i) // fill pixels between x0 and x1 1753 scanline[i] = scanline[i] + (stbtt_uint8) max_weight; 1754 } 1755 } 1756 } 1757 } 1758 1759 e = e->next; 1760 } 1761 } 1762 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) 1764 { 1765 stbtt__hheap hh = { 0, 0, 0 }; 1766 stbtt__active_edge *active = NULL; 1767 int y,j=0; 1768 int max_weight = (255 / vsubsample); // weight per vertical scanline 1769 int s; // vertical subsample index 1770 unsigned char scanline_data[512], *scanline; 1771 1772 if (result->w > 512) 1773 scanline = (unsigned char *) STBTT_malloc(result->w, userdata); 1774 else 1775 scanline = scanline_data; 1776 1777 y = off_y * vsubsample; 1778 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; 1779 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; 1786 1787 // update all active edges; 1788 // remove all active edges that terminate before the center of this scanline 1789 while (*step) { 1790 stbtt__active_edge * z = *step; 1791 if (z->ey <= scan_y) { 1792 *step = z->next; // delete from list 1793 STBTT_assert(z->direction); 1794 z->direction = 0; 1795 stbtt__hheap_free(&hh, z); 1796 } else { 1797 z->x += z->dx; // advance to position for current scanline 1798 step = &((*step)->next); // advance through list 1799 } 1800 } 1801 1802 // resort the list if needed 1803 for(;;) { 1804 int changed=0; 1805 step = &active; 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; 1810 1811 t->next = q->next; 1812 q->next = t; 1813 *step = q; 1814 changed = 1; 1815 } 1816 step = &(*step)->next; 1817 } 1818 if (!changed) break; 1819 } 1820 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); 1825 // find insertion point 1826 if (active == NULL) 1827 active = z; 1828 else if (z->x < active->x) { 1829 // insert at front 1830 z->next = active; 1831 active = z; 1832 } else { 1833 // find thing to insert AFTER 1834 stbtt__active_edge *p = active; 1835 while (p->next && p->next->x < z->x) 1836 p = p->next; 1837 // at this point, p->next->x is NOT < z->x 1838 z->next = p->next; 1839 p->next = z; 1840 } 1841 } 1842 ++e; 1843 } 1844 1845 // now process all active edges in XOR fashion 1846 if (active) 1847 stbtt__fill_active_edges(scanline, result->w, active, max_weight); 1848 1849 ++y; 1850 } 1851 STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); 1852 ++j; 1853 } 1854 1855 stbtt__hheap_cleanup(&hh, userdata); 1856 1857 if (scanline != scanline_data) 1858 STBTT_free(scanline, userdata); 1859 } 1860 1861 #elif STBTT_RASTERIZER_VERSION == 2 1862 1863 // the edge passed in here does not cross the vertical line at x or the vertical line at x+1 1864 // (i.e. it has already been clipped to those) 1865 static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) 1866 { 1867 if (y0 == y1) return; 1868 STBTT_assert(y0 < y1); 1869 STBTT_assert(e->sy <= e->ey); 1870 if (y0 > e->ey) return; 1871 if (y1 < e->sy) return; 1872 if (y0 < e->sy) { 1873 x0 += (x1-x0) * (e->sy - y0) / (y1-y0); 1874 y0 = e->sy; 1875 } 1876 if (y1 > e->ey) { 1877 x1 += (x1-x0) * (e->ey - y1) / (y1-y0); 1878 y1 = e->ey; 1879 } 1880 1881 if (x0 == x) 1882 STBTT_assert(x1 <= x+1); 1883 else if (x0 == x+1) 1884 STBTT_assert(x1 >= x); 1885 else if (x0 <= x) 1886 STBTT_assert(x1 <= x); 1887 else if (x0 >= x+1) 1888 STBTT_assert(x1 >= x+1); 1889 else 1890 STBTT_assert(x1 >= x && x1 <= x+1); 1891 1892 if (x0 <= x && x1 <= x) 1893 scanline[x] += e->direction * (y1-y0); 1894 else if (x0 >= x+1 && x1 >= x+1) 1895 ; 1896 else { 1897 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); 1898 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position 1899 } 1900 } 1901 1902 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) 1903 { 1904 float y_bottom = y_top+1; 1905 1906 while (e) { 1907 // brute force every pixel 1908 1909 // compute intersection points with top & bottom 1910 STBTT_assert(e->ey >= y_top); 1911 1912 if (e->fdx == 0) { 1913 float x0 = e->fx; 1914 if (x0 < len) { 1915 if (x0 >= 0) { 1916 stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); 1917 stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); 1918 } else { 1919 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); 1920 } 1921 } 1922 } else { 1923 float x0 = e->fx; 1924 float dx = e->fdx; 1925 float xb = x0 + dx; 1926 float x_top, x_bottom; 1927 float sy0,sy1; 1928 float dy = e->fdy; 1929 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); 1930 1931 // compute endpoints of line segment clipped to this scanline (if the 1932 // line segment starts on this scanline. x0 is the intersection of the 1933 // line with y_top, but that may be off the line segment. 1934 if (e->sy > y_top) { 1935 x_top = x0 + dx * (e->sy - y_top); 1936 sy0 = e->sy; 1937 } else { 1938 x_top = x0; 1939 sy0 = y_top; 1940 } 1941 if (e->ey < y_bottom) { 1942 x_bottom = x0 + dx * (e->ey - y_top); 1943 sy1 = e->ey; 1944 } else { 1945 x_bottom = xb; 1946 sy1 = y_bottom; 1947 } 1948 1949 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { 1950 // from here on, we don't have to range check x values 1951 1952 if ((int) x_top == (int) x_bottom) { 1953 float height; 1954 // simple case, only spans one pixel 1955 int x = (int) x_top; 1956 height = sy1 - sy0; 1957 STBTT_assert(x >= 0 && x < len); 1958 scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; 1959 scanline_fill[x] += e->direction * height; // everything right of this pixel is filled 1960 } else { 1961 int x,x1,x2; 1962 float y_crossing, step, sign, area; 1963 // covers 2+ pixels 1964 if (x_top > x_bottom) { 1965 // flip scanline vertically; signed area is the same 1966 float t; 1967 sy0 = y_bottom - (sy0 - y_top); 1968 sy1 = y_bottom - (sy1 - y_top); 1969 t = sy0, sy0 = sy1, sy1 = t; 1970 t = x_bottom, x_bottom = x_top, x_top = t; 1971 dx = -dx; 1972 dy = -dy; 1973 t = x0, x0 = xb, xb = t; 1974 } 1975 1976 x1 = (int) x_top; 1977 x2 = (int) x_bottom; 1978 // compute intersection with y axis at x1+1 1979 y_crossing = (x1+1 - x0) * dy + y_top; 1980 1981 sign = e->direction; 1982 // area of the rectangle covered from y0..y_crossing 1983 area = sign * (y_crossing-sy0); 1984 // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) 1985 scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); 1986 1987 step = sign * dy; 1988 for (x = x1+1; x < x2; ++x) { 1989 scanline[x] += area + step/2; 1990 area += step; 1991 } 1992 y_crossing += dy * (x2 - (x1+1)); 1993 1994 STBTT_assert(fabs(area) <= 1.01f); 1995 1996 scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); 1997 1998 scanline_fill[x2] += sign * (sy1-sy0); 1999 } 2000 } else { 2001 // if edge goes outside of box we're drawing, we require 2002 // clipping logic. since this does not match the intended use 2003 // of this library, we use a different, very slow brute 2004 // force implementation 2005 int x; 2006 for (x=0; x < len; ++x) { 2007 // cases: 2008 // 2009 // there can be up to two intersections with the pixel. any intersection 2010 // with left or right edges can be handled by splitting into two (or three) 2011 // regions. intersections with top & bottom do not necessitate case-wise logic. 2012 // 2013 // the old way of doing this found the intersections with the left & right edges, 2014 // then used some simple logic to produce up to three segments in sorted order 2015 // from top-to-bottom. however, this had a problem: if an x edge was epsilon 2016 // across the x border, then the corresponding y position might not be distinct 2017 // from the other y segment, and it might ignored as an empty segment. to avoid 2018 // that, we need to explicitly produce segments based on x positions. 2019 2020 // rename variables to clear pairs 2021 float y0 = y_top; 2022 float x1 = (float) (x); 2023 float x2 = (float) (x+1); 2024 float x3 = xb; 2025 float y3 = y_bottom; 2026 float y1,y2; 2027 2028 // x = e->x + e->dx * (y-y_top) 2029 // (y-y_top) = (x - e->x) / e->dx 2030 // y = (x - e->x) / e->dx + y_top 2031 y1 = (x - x0) / dx + y_top; 2032 y2 = (x+1 - x0) / dx + y_top; 2033 2034 if (x0 < x1 && x3 > x2) { // three segments descending down-right 2035 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 2036 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); 2037 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 2038 } else if (x3 < x1 && x0 > x2) { // three segments descending down-left 2039 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 2040 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); 2041 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 2042 } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right 2043 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 2044 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 2045 } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left 2046 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 2047 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 2048 } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right 2049 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 2050 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 2051 } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left 2052 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 2053 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 2054 } else { // one segment 2055 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); 2056 } 2057 } 2058 } 2059 } 2060 e = e->next; 2061 } 2062 } 2063 2064 // directly AA rasterize edges w/o supersampling 2065 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) 2066 { 2067 stbtt__hheap hh = { 0, 0, 0 }; 2068 stbtt__active_edge *active = NULL; 2069 int y,j=0, i; 2070 float scanline_data[129], *scanline, *scanline2; 2071 2072 if (result->w > 64) 2073 scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); 2074 else 2075 scanline = scanline_data; 2076 2077 scanline2 = scanline + result->w; 2078 2079 y = off_y; 2080 e[n].y0 = (float) (off_y + result->h) + 1; 2081 2082 while (j < result->h) { 2083 // find center of pixel for this scanline 2084 float scan_y_top = y + 0.0f; 2085 float scan_y_bottom = y + 1.0f; 2086 stbtt__active_edge **step = &active; 2087 2088 STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); 2089 STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); 2090 2091 // update all active edges; 2092 // remove all active edges that terminate before the top of this scanline 2093 while (*step) { 2094 stbtt__active_edge * z = *step; 2095 if (z->ey <= scan_y_top) { 2096 *step = z->next; // delete from list 2097 STBTT_assert(z->direction); 2098 z->direction = 0; 2099 stbtt__hheap_free(&hh, z); 2100 } else { 2101 step = &((*step)->next); // advance through list 2102 } 2103 } 2104 2105 // insert all edges that start before the bottom of this scanline 2106 while (e->y0 <= scan_y_bottom) { 2107 if (e->y0 != e->y1) { 2108 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); 2109 STBTT_assert(z->ey >= scan_y_top); 2110 // insert at front 2111 z->next = active; 2112 active = z; 2113 } 2114 ++e; 2115 } 2116 2117 // now process all active edges 2118 if (active) 2119 stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); 2120 2121 { 2122 float sum = 0; 2123 for (i=0; i < result->w; ++i) { 2124 float k; 2125 int m; 2126 sum += scanline2[i]; 2127 k = scanline[i] + sum; 2128 k = (float) STBTT_fabs(k)*255 + 0.5f; 2129 m = (int) k; 2130 if (m > 255) m = 255; 2131 result->pixels[j*result->stride + i] = (unsigned char) m; 2132 } 2133 } 2134 // advance all the edges 2135 step = &active; 2136 while (*step) { 2137 stbtt__active_edge *z = *step; 2138 z->fx += z->fdx; // advance to position for current scanline 2139 step = &((*step)->next); // advance through list 2140 } 2141 2142 ++y; 2143 ++j; 2144 } 2145 2146 stbtt__hheap_cleanup(&hh, userdata); 2147 2148 if (scanline != scanline_data) 2149 STBTT_free(scanline, userdata); 2150 } 2151 #else 2152 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 2153 #endif 2154 2155 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) 2156 2157 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) 2158 { 2159 int i,j; 2160 for (i=1; i < n; ++i) { 2161 stbtt__edge t = p[i], *a = &t; 2162 j = i; 2163 while (j > 0) { 2164 stbtt__edge *b = &p[j-1]; 2165 int c = STBTT__COMPARE(a,b); 2166 if (!c) break; 2167 p[j] = p[j-1]; 2168 --j; 2169 } 2170 if (i != j) 2171 p[j] = t; 2172 } 2173 } 2174 2175 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) 2176 { 2177 /* threshhold for transitioning to insertion sort */ 2178 while (n > 12) { 2179 stbtt__edge t; 2180 int c01,c12,c,m,i,j; 2181 2182 /* compute median of three */ 2183 m = n >> 1; 2184 c01 = STBTT__COMPARE(&p[0],&p[m]); 2185 c12 = STBTT__COMPARE(&p[m],&p[n-1]); 2186 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ 2187 if (c01 != c12) { 2188 /* otherwise, we'll need to swap something else to middle */ 2189 int z; 2190 c = STBTT__COMPARE(&p[0],&p[n-1]); 2191 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ 2192 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ 2193 z = (c == c12) ? 0 : n-1; 2194 t = p[z]; 2195 p[z] = p[m]; 2196 p[m] = t; 2197 } 2198 /* now p[m] is the median-of-three */ 2199 /* swap it to the beginning so it won't move around */ 2200 t = p[0]; 2201 p[0] = p[m]; 2202 p[m] = t; 2203 2204 /* partition loop */ 2205 i=1; 2206 j=n-1; 2207 for(;;) { 2208 /* handling of equality is crucial here */ 2209 /* for sentinels & efficiency with duplicates */ 2210 for (;;++i) { 2211 if (!STBTT__COMPARE(&p[i], &p[0])) break; 2212 } 2213 for (;;--j) { 2214 if (!STBTT__COMPARE(&p[0], &p[j])) break; 2215 } 2216 /* make sure we haven't crossed */ 2217 if (i >= j) break; 2218 t = p[i]; 2219 p[i] = p[j]; 2220 p[j] = t; 2221 2222 ++i; 2223 --j; 2224 } 2225 /* recurse on smaller side, iterate on larger */ 2226 if (j < (n-i)) { 2227 stbtt__sort_edges_quicksort(p,j); 2228 p = p+i; 2229 n = n-i; 2230 } else { 2231 stbtt__sort_edges_quicksort(p+i, n-i); 2232 n = j; 2233 } 2234 } 2235 } 2236 2237 static void stbtt__sort_edges(stbtt__edge *p, int n) 2238 { 2239 stbtt__sort_edges_quicksort(p, n); 2240 stbtt__sort_edges_ins_sort(p, n); 2241 } 2242 2243 typedef struct 2244 { 2245 float x,y; 2246 } stbtt__point; 2247 2248 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) 2249 { 2250 float y_scale_inv = invert ? -scale_y : scale_y; 2251 stbtt__edge *e; 2252 int n,i,j,k,m; 2253 #if STBTT_RASTERIZER_VERSION == 1 2254 int vsubsample = result->h < 8 ? 15 : 5; 2255 #elif STBTT_RASTERIZER_VERSION == 2 2256 int vsubsample = 1; 2257 #else 2258 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 2259 #endif 2260 // vsubsample should divide 255 evenly; otherwise we won't reach full opacity 2261 2262 // now we have to blow out the windings into explicit edge lists 2263 n = 0; 2264 for (i=0; i < windings; ++i) 2265 n += wcount[i]; 2266 2267 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel 2268 if (e == 0) return; 2269 n = 0; 2270 2271 m=0; 2272 for (i=0; i < windings; ++i) { 2273 stbtt__point *p = pts + m; 2274 m += wcount[i]; 2275 j = wcount[i]-1; 2276 for (k=0; k < wcount[i]; j=k++) { 2277 int a=k,b=j; 2278 // skip the edge if horizontal 2279 if (p[j].y == p[k].y) 2280 continue; 2281 // add edge from j to k to the list 2282 e[n].invert = 0; 2283 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { 2284 e[n].invert = 1; 2285 a=j,b=k; 2286 } 2287 e[n].x0 = p[a].x * scale_x + shift_x; 2288 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; 2289 e[n].x1 = p[b].x * scale_x + shift_x; 2290 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; 2291 ++n; 2292 } 2293 } 2294 2295 // now sort the edges by their highest point (should snap to integer, and then by x) 2296 //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); 2297 stbtt__sort_edges(e, n); 2298 2299 // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule 2300 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); 2301 2302 STBTT_free(e, userdata); 2303 } 2304 2305 static void stbtt__add_point(stbtt__point *points, int n, float x, float y) 2306 { 2307 if (!points) return; // during first pass, it's unallocated 2308 points[n].x = x; 2309 points[n].y = y; 2310 } 2311 2312 // tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching 2313 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) 2314 { 2315 // midpoint 2316 float mx = (x0 + 2*x1 + x2)/4; 2317 float my = (y0 + 2*y1 + y2)/4; 2318 // versus directly drawn line 2319 float dx = (x0+x2)/2 - mx; 2320 float dy = (y0+y2)/2 - my; 2321 if (n > 16) // 65536 segments on one curve better be enough! 2322 return 1; 2323 if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA 2324 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); 2325 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); 2326 } else { 2327 stbtt__add_point(points, *num_points,x2,y2); 2328 *num_points = *num_points+1; 2329 } 2330 return 1; 2331 } 2332 2333 // returns number of contours 2334 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) 2335 { 2336 stbtt__point *points=0; 2337 int num_points=0; 2338 2339 float objspace_flatness_squared = objspace_flatness * objspace_flatness; 2340 int i,n=0,start=0, pass; 2341 2342 // count how many "moves" there are to get the contour count 2343 for (i=0; i < num_verts; ++i) 2344 if (vertices[i].type == STBTT_vmove) 2345 ++n; 2346 2347 *num_contours = n; 2348 if (n == 0) return 0; 2349 2350 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); 2351 2352 if (*contour_lengths == 0) { 2353 *num_contours = 0; 2354 return 0; 2355 } 2356 2357 // make two passes through the points so we don't need to realloc 2358 for (pass=0; pass < 2; ++pass) { 2359 float x=0,y=0; 2360 if (pass == 1) { 2361 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); 2362 if (points == NULL) goto error; 2363 } 2364 num_points = 0; 2365 n= -1; 2366 for (i=0; i < num_verts; ++i) { 2367 switch (vertices[i].type) { 2368 case STBTT_vmove: 2369 // start the next contour 2370 if (n >= 0) 2371 (*contour_lengths)[n] = num_points - start; 2372 ++n; 2373 start = num_points; 2374 2375 x = vertices[i].x, y = vertices[i].y; 2376 stbtt__add_point(points, num_points++, x,y); 2377 break; 2378 case STBTT_vline: 2379 x = vertices[i].x, y = vertices[i].y; 2380 stbtt__add_point(points, num_points++, x, y); 2381 break; 2382 case STBTT_vcurve: 2383 stbtt__tesselate_curve(points, &num_points, x,y, 2384 vertices[i].cx, vertices[i].cy, 2385 vertices[i].x, vertices[i].y, 2386 objspace_flatness_squared, 0); 2387 x = vertices[i].x, y = vertices[i].y; 2388 break; 2389 } 2390 } 2391 (*contour_lengths)[n] = num_points - start; 2392 } 2393 2394 return points; 2395 error: 2396 STBTT_free(points, userdata); 2397 STBTT_free(*contour_lengths, userdata); 2398 *contour_lengths = 0; 2399 *num_contours = 0; 2400 return NULL; 2401 } 2402 2403 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) 2404 { 2405 float scale = scale_x > scale_y ? scale_y : scale_x; 2406 int winding_count, *winding_lengths; 2407 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); 2408 if (windings) { 2409 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); 2410 STBTT_free(winding_lengths, userdata); 2411 STBTT_free(windings, userdata); 2412 } 2413 } 2414 2415 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) 2416 { 2417 STBTT_free(bitmap, userdata); 2418 } 2419 2420 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) 2421 { 2422 int ix0,iy0,ix1,iy1; 2423 stbtt__bitmap gbm; 2424 stbtt_vertex *vertices; 2425 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); 2426 2427 if (scale_x == 0) scale_x = scale_y; 2428 if (scale_y == 0) { 2429 if (scale_x == 0) { 2430 STBTT_free(vertices, info->userdata); 2431 return NULL; 2432 } 2433 scale_y = scale_x; 2434 } 2435 2436 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); 2437 2438 // now we get the size 2439 gbm.w = (ix1 - ix0); 2440 gbm.h = (iy1 - iy0); 2441 gbm.pixels = NULL; // in case we error 2442 2443 if (width ) *width = gbm.w; 2444 if (height) *height = gbm.h; 2445 if (xoff ) *xoff = ix0; 2446 if (yoff ) *yoff = iy0; 2447 2448 if (gbm.w && gbm.h) { 2449 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); 2450 if (gbm.pixels) { 2451 gbm.stride = gbm.w; 2452 2453 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); 2454 } 2455 } 2456 STBTT_free(vertices, info->userdata); 2457 return gbm.pixels; 2458 } 2459 2460 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) 2461 { 2462 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); 2463 } 2464 2465 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) 2466 { 2467 int ix0,iy0; 2468 stbtt_vertex *vertices; 2469 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); 2470 stbtt__bitmap gbm; 2471 2472 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); 2473 gbm.pixels = output; 2474 gbm.w = out_w; 2475 gbm.h = out_h; 2476 gbm.stride = out_stride; 2477 2478 if (gbm.w && gbm.h) 2479 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); 2480 2481 STBTT_free(vertices, info->userdata); 2482 } 2483 2484 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) 2485 { 2486 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); 2487 } 2488 2489 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) 2490 { 2491 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); 2492 } 2493 2494 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) 2495 { 2496 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); 2497 } 2498 2499 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) 2500 { 2501 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); 2502 } 2503 2504 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) 2505 { 2506 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); 2507 } 2508 2509 ////////////////////////////////////////////////////////////////////////////// 2510 // 2511 // bitmap baking 2512 // 2513 // This is SUPER-CRAPPY packing to keep source code small 2514 2515 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) 2516 float pixel_height, // height of font in pixels 2517 unsigned char *pixels, int pw, int ph, // bitmap to be filled in 2518 int first_char, int num_chars, // characters to bake 2519 stbtt_bakedchar *chardata) 2520 { 2521 float scale; 2522 int x,y,bottom_y, i; 2523 stbtt_fontinfo f; 2524 if (!stbtt_InitFont(&f, data, offset)) 2525 return -1; 2526 STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels 2527 x=y=1; 2528 bottom_y = 1; 2529 2530 scale = stbtt_ScaleForPixelHeight(&f, pixel_height); 2531 2532 for (i=0; i < num_chars; ++i) { 2533 int advance, lsb, x0,y0,x1,y1,gw,gh; 2534 int g = stbtt_FindGlyphIndex(&f, first_char + i); 2535 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); 2536 stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); 2537 gw = x1-x0; 2538 gh = y1-y0; 2539 if (x + gw + 1 >= pw) 2540 y = bottom_y, x = 1; // advance to next row 2541 if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row 2542 return -i; 2543 STBTT_assert(x+gw < pw); 2544 STBTT_assert(y+gh < ph); 2545 stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); 2546 chardata[i].x0 = (stbtt_int16) x; 2547 chardata[i].y0 = (stbtt_int16) y; 2548 chardata[i].x1 = (stbtt_int16) (x + gw); 2549 chardata[i].y1 = (stbtt_int16) (y + gh); 2550 chardata[i].xadvance = scale * advance; 2551 chardata[i].xoff = (float) x0; 2552 chardata[i].yoff = (float) y0; 2553 x = x + gw + 1; 2554 if (y+gh+1 > bottom_y) 2555 bottom_y = y+gh+1; 2556 } 2557 return bottom_y; 2558 } 2559 2560 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) 2561 { 2562 float d3d_bias = opengl_fillrule ? 0 : -0.5f; 2563 float ipw = 1.0f / pw, iph = 1.0f / ph; 2564 stbtt_bakedchar *b = chardata + char_index; 2565 int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); 2566 int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); 2567 2568 q->x0 = round_x + d3d_bias; 2569 q->y0 = round_y + d3d_bias; 2570 q->x1 = round_x + b->x1 - b->x0 + d3d_bias; 2571 q->y1 = round_y + b->y1 - b->y0 + d3d_bias; 2572 2573 q->s0 = b->x0 * ipw; 2574 q->t0 = b->y0 * iph; 2575 q->s1 = b->x1 * ipw; 2576 q->t1 = b->y1 * iph; 2577 2578 *xpos += b->xadvance; 2579 } 2580 2581 ////////////////////////////////////////////////////////////////////////////// 2582 // 2583 // rectangle packing replacement routines if you don't have stb_rect_pack.h 2584 // 2585 2586 #ifndef STB_RECT_PACK_VERSION 2587 #ifdef _MSC_VER 2588 #define STBTT__NOTUSED(v) (void)(v) 2589 #else 2590 #define STBTT__NOTUSED(v) (void)sizeof(v) 2591 #endif 2592 2593 typedef int stbrp_coord; 2594 2595 //////////////////////////////////////////////////////////////////////////////////// 2596 // // 2597 // // 2598 // COMPILER WARNING ?!?!? // 2599 // // 2600 // // 2601 // if you get a compile warning due to these symbols being defined more than // 2602 // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // 2603 // // 2604 //////////////////////////////////////////////////////////////////////////////////// 2605 2606 typedef struct 2607 { 2608 int width,height; 2609 int x,y,bottom_y; 2610 } stbrp_context; 2611 2612 typedef struct 2613 { 2614 unsigned char x; 2615 } stbrp_node; 2616 2617 struct stbrp_rect 2618 { 2619 stbrp_coord x,y; 2620 int id,w,h,was_packed; 2621 }; 2622 2623 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) 2624 { 2625 con->width = pw; 2626 con->height = ph; 2627 con->x = 0; 2628 con->y = 0; 2629 con->bottom_y = 0; 2630 STBTT__NOTUSED(nodes); 2631 STBTT__NOTUSED(num_nodes); 2632 } 2633 2634 static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) 2635 { 2636 int i; 2637 for (i=0; i < num_rects; ++i) { 2638 if (con->x + rects[i].w > con->width) { 2639 con->x = 0; 2640 con->y = con->bottom_y; 2641 } 2642 if (con->y + rects[i].h > con->height) 2643 break; 2644 rects[i].x = con->x; 2645 rects[i].y = con->y; 2646 rects[i].was_packed = 1; 2647 con->x += rects[i].w; 2648 if (con->y + rects[i].h > con->bottom_y) 2649 con->bottom_y = con->y + rects[i].h; 2650 } 2651 for ( ; i < num_rects; ++i) 2652 rects[i].was_packed = 0; 2653 } 2654 #endif 2655 2656 ////////////////////////////////////////////////////////////////////////////// 2657 // 2658 // bitmap baking 2659 // 2660 // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If 2661 // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. 2662 2663 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) 2664 { 2665 stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); 2666 int num_nodes = pw - padding; 2667 stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); 2668 2669 if (context == NULL || nodes == NULL) { 2670 if (context != NULL) STBTT_free(context, alloc_context); 2671 if (nodes != NULL) STBTT_free(nodes , alloc_context); 2672 return 0; 2673 } 2674 2675 spc->user_allocator_context = alloc_context; 2676 spc->width = pw; 2677 spc->height = ph; 2678 spc->pixels = pixels; 2679 spc->pack_info = context; 2680 spc->nodes = nodes; 2681 spc->padding = padding; 2682 spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; 2683 spc->h_oversample = 1; 2684 spc->v_oversample = 1; 2685 2686 stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); 2687 2688 if (pixels) 2689 STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels 2690 2691 return 1; 2692 } 2693 2694 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) 2695 { 2696 STBTT_free(spc->nodes , spc->user_allocator_context); 2697 STBTT_free(spc->pack_info, spc->user_allocator_context); 2698 } 2699 2700 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) 2701 { 2702 STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); 2703 STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); 2704 if (h_oversample <= STBTT_MAX_OVERSAMPLE) 2705 spc->h_oversample = h_oversample; 2706 if (v_oversample <= STBTT_MAX_OVERSAMPLE) 2707 spc->v_oversample = v_oversample; 2708 } 2709 2710 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) 2711 2712 static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) 2713 { 2714 unsigned char buffer[STBTT_MAX_OVERSAMPLE]; 2715 int safe_w = w - kernel_width; 2716 int j; 2717 for (j=0; j < h; ++j) { 2718 int i; 2719 unsigned int total; 2720 STBTT_memset(buffer, 0, kernel_width); 2721 2722 total = 0; 2723 2724 // make kernel_width a constant in common cases so compiler can optimize out the divide 2725 switch (kernel_width) { 2726 case 2: 2727 for (i=0; i <= safe_w; ++i) { 2728 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 2729 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 2730 pixels[i] = (unsigned char) (total / 2); 2731 } 2732 break; 2733 case 3: 2734 for (i=0; i <= safe_w; ++i) { 2735 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 2736 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 2737 pixels[i] = (unsigned char) (total / 3); 2738 } 2739 break; 2740 case 4: 2741 for (i=0; i <= safe_w; ++i) { 2742 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 2743 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 2744 pixels[i] = (unsigned char) (total / 4); 2745 } 2746 break; 2747 case 5: 2748 for (i=0; i <= safe_w; ++i) { 2749 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 2750 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 2751 pixels[i] = (unsigned char) (total / 5); 2752 } 2753 break; 2754 default: 2755 for (i=0; i <= safe_w; ++i) { 2756 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 2757 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 2758 pixels[i] = (unsigned char) (total / kernel_width); 2759 } 2760 break; 2761 } 2762 2763 for (; i < w; ++i) { 2764 STBTT_assert(pixels[i] == 0); 2765 total -= buffer[i & STBTT__OVER_MASK]; 2766 pixels[i] = (unsigned char) (total / kernel_width); 2767 } 2768 2769 pixels += stride_in_bytes; 2770 } 2771 } 2772 2773 static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) 2774 { 2775 unsigned char buffer[STBTT_MAX_OVERSAMPLE]; 2776 int safe_h = h - kernel_width; 2777 int j; 2778 for (j=0; j < w; ++j) { 2779 int i; 2780 unsigned int total; 2781 STBTT_memset(buffer, 0, kernel_width); 2782 2783 total = 0; 2784 2785 // make kernel_width a constant in common cases so compiler can optimize out the divide 2786 switch (kernel_width) { 2787 case 2: 2788 for (i=0; i <= safe_h; ++i) { 2789 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 2790 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 2791 pixels[i*stride_in_bytes] = (unsigned char) (total / 2); 2792 } 2793 break; 2794 case 3: 2795 for (i=0; i <= safe_h; ++i) { 2796 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 2797 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 2798 pixels[i*stride_in_bytes] = (unsigned char) (total / 3); 2799 } 2800 break; 2801 case 4: 2802 for (i=0; i <= safe_h; ++i) { 2803 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 2804 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 2805 pixels[i*stride_in_bytes] = (unsigned char) (total / 4); 2806 } 2807 break; 2808 case 5: 2809 for (i=0; i <= safe_h; ++i) { 2810 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 2811 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 2812 pixels[i*stride_in_bytes] = (unsigned char) (total / 5); 2813 } 2814 break; 2815 default: 2816 for (i=0; i <= safe_h; ++i) { 2817 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 2818 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 2819 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); 2820 } 2821 break; 2822 } 2823 2824 for (; i < h; ++i) { 2825 STBTT_assert(pixels[i*stride_in_bytes] == 0); 2826 total -= buffer[i & STBTT__OVER_MASK]; 2827 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); 2828 } 2829 2830 pixels += 1; 2831 } 2832 } 2833 2834 static float stbtt__oversample_shift(int oversample) 2835 { 2836 if (!oversample) 2837 return 0.0f; 2838 2839 // The prefilter is a box filter of width "oversample", 2840 // which shifts phase by (oversample - 1)/2 pixels in 2841 // oversampled space. We want to shift in the opposite 2842 // direction to counter this. 2843 return (float)-(oversample - 1) / (2.0f * (float)oversample); 2844 } 2845 2846 // rects array must be big enough to accommodate all characters in the given ranges 2847 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) 2848 { 2849 int i,j,k; 2850 2851 k=0; 2852 for (i=0; i < num_ranges; ++i) { 2853 float fh = ranges[i].font_size; 2854 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); 2855 ranges[i].h_oversample = (unsigned char) spc->h_oversample; 2856 ranges[i].v_oversample = (unsigned char) spc->v_oversample; 2857 for (j=0; j < ranges[i].num_chars; ++j) { 2858 int x0,y0,x1,y1; 2859 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; 2860 int glyph = stbtt_FindGlyphIndex(info, codepoint); 2861 stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, 2862 scale * spc->h_oversample, 2863 scale * spc->v_oversample, 2864 0,0, 2865 &x0,&y0,&x1,&y1); 2866 rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); 2867 rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); 2868 ++k; 2869 } 2870 } 2871 2872 return k; 2873 } 2874 2875 // rects array must be big enough to accommodate all characters in the given ranges 2876 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) 2877 { 2878 int i,j,k, return_value = 1; 2879 2880 // save current values 2881 int old_h_over = spc->h_oversample; 2882 int old_v_over = spc->v_oversample; 2883 2884 k = 0; 2885 for (i=0; i < num_ranges; ++i) { 2886 float fh = ranges[i].font_size; 2887 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); 2888 float recip_h,recip_v,sub_x,sub_y; 2889 spc->h_oversample = ranges[i].h_oversample; 2890 spc->v_oversample = ranges[i].v_oversample; 2891 recip_h = 1.0f / spc->h_oversample; 2892 recip_v = 1.0f / spc->v_oversample; 2893 sub_x = stbtt__oversample_shift(spc->h_oversample); 2894 sub_y = stbtt__oversample_shift(spc->v_oversample); 2895 for (j=0; j < ranges[i].num_chars; ++j) { 2896 stbrp_rect *r = &rects[k]; 2897 if (r->was_packed) { 2898 stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; 2899 int advance, lsb, x0,y0,x1,y1; 2900 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; 2901 int glyph = stbtt_FindGlyphIndex(info, codepoint); 2902 stbrp_coord pad = (stbrp_coord) spc->padding; 2903 2904 // pad on left and top 2905 r->x += pad; 2906 r->y += pad; 2907 r->w -= pad; 2908 r->h -= pad; 2909 stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); 2910 stbtt_GetGlyphBitmapBox(info, glyph, 2911 scale * spc->h_oversample, 2912 scale * spc->v_oversample, 2913 &x0,&y0,&x1,&y1); 2914 stbtt_MakeGlyphBitmapSubpixel(info, 2915 spc->pixels + r->x + r->y*spc->stride_in_bytes, 2916 r->w - spc->h_oversample+1, 2917 r->h - spc->v_oversample+1, 2918 spc->stride_in_bytes, 2919 scale * spc->h_oversample, 2920 scale * spc->v_oversample, 2921 0,0, 2922 glyph); 2923 2924 if (spc->h_oversample > 1) 2925 stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 2926 r->w, r->h, spc->stride_in_bytes, 2927 spc->h_oversample); 2928 2929 if (spc->v_oversample > 1) 2930 stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 2931 r->w, r->h, spc->stride_in_bytes, 2932 spc->v_oversample); 2933 2934 bc->x0 = (stbtt_int16) r->x; 2935 bc->y0 = (stbtt_int16) r->y; 2936 bc->x1 = (stbtt_int16) (r->x + r->w); 2937 bc->y1 = (stbtt_int16) (r->y + r->h); 2938 bc->xadvance = scale * advance; 2939 bc->xoff = (float) x0 * recip_h + sub_x; 2940 bc->yoff = (float) y0 * recip_v + sub_y; 2941 bc->xoff2 = (x0 + r->w) * recip_h + sub_x; 2942 bc->yoff2 = (y0 + r->h) * recip_v + sub_y; 2943 } else { 2944 return_value = 0; // if any fail, report failure 2945 } 2946 2947 ++k; 2948 } 2949 } 2950 2951 // restore original values 2952 spc->h_oversample = old_h_over; 2953 spc->v_oversample = old_v_over; 2954 2955 return return_value; 2956 } 2957 2958 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) 2959 { 2960 stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); 2961 } 2962 2963 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) 2964 { 2965 stbtt_fontinfo info; 2966 int i,j,n, return_value = 1; 2967 //stbrp_context *context = (stbrp_context *) spc->pack_info; 2968 stbrp_rect *rects; 2969 2970 // flag all characters as NOT packed 2971 for (i=0; i < num_ranges; ++i) 2972 for (j=0; j < ranges[i].num_chars; ++j) 2973 ranges[i].chardata_for_range[j].x0 = 2974 ranges[i].chardata_for_range[j].y0 = 2975 ranges[i].chardata_for_range[j].x1 = 2976 ranges[i].chardata_for_range[j].y1 = 0; 2977 2978 n = 0; 2979 for (i=0; i < num_ranges; ++i) 2980 n += ranges[i].num_chars; 2981 2982 rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); 2983 if (rects == NULL) 2984 return 0; 2985 2986 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); 2987 2988 n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); 2989 2990 stbtt_PackFontRangesPackRects(spc, rects, n); 2991 2992 return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); 2993 2994 STBTT_free(rects, spc->user_allocator_context); 2995 return return_value; 2996 } 2997 2998 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, 2999 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) 3000 { 3001 stbtt_pack_range range; 3002 range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; 3003 range.array_of_unicode_codepoints = NULL; 3004 range.num_chars = num_chars_in_range; 3005 range.chardata_for_range = chardata_for_range; 3006 range.font_size = font_size; 3007 return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); 3008 } 3009 3010 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) 3011 { 3012 float ipw = 1.0f / pw, iph = 1.0f / ph; 3013 stbtt_packedchar *b = chardata + char_index; 3014 3015 if (align_to_integer) { 3016 float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); 3017 float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); 3018 q->x0 = x; 3019 q->y0 = y; 3020 q->x1 = x + b->xoff2 - b->xoff; 3021 q->y1 = y + b->yoff2 - b->yoff; 3022 } else { 3023 q->x0 = *xpos + b->xoff; 3024 q->y0 = *ypos + b->yoff; 3025 q->x1 = *xpos + b->xoff2; 3026 q->y1 = *ypos + b->yoff2; 3027 } 3028 3029 q->s0 = b->x0 * ipw; 3030 q->t0 = b->y0 * iph; 3031 q->s1 = b->x1 * ipw; 3032 q->t1 = b->y1 * iph; 3033 3034 *xpos += b->xadvance; 3035 } 3036 3037 3038 ////////////////////////////////////////////////////////////////////////////// 3039 // 3040 // font name matching -- recommended not to use this 3041 // 3042 3043 // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string 3044 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2) 3045 { 3046 stbtt_int32 i=0; 3047 3048 // convert utf16 to utf8 and compare the results while converting 3049 while (len2) { 3050 stbtt_uint16 ch = s2[0]*256 + s2[1]; 3051 if (ch < 0x80) { 3052 if (i >= len1) return -1; 3053 if (s1[i++] != ch) return -1; 3054 } else if (ch < 0x800) { 3055 if (i+1 >= len1) return -1; 3056 if (s1[i++] != 0xc0 + (ch >> 6)) return -1; 3057 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; 3058 } else if (ch >= 0xd800 && ch < 0xdc00) { 3059 stbtt_uint32 c; 3060 stbtt_uint16 ch2 = s2[2]*256 + s2[3]; 3061 if (i+3 >= len1) return -1; 3062 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; 3063 if (s1[i++] != 0xf0 + (c >> 18)) return -1; 3064 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; 3065 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; 3066 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; 3067 s2 += 2; // plus another 2 below 3068 len2 -= 2; 3069 } else if (ch >= 0xdc00 && ch < 0xe000) { 3070 return -1; 3071 } else { 3072 if (i+2 >= len1) return -1; 3073 if (s1[i++] != 0xe0 + (ch >> 12)) return -1; 3074 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; 3075 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; 3076 } 3077 s2 += 2; 3078 len2 -= 2; 3079 } 3080 return i; 3081 } 3082 3083 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) 3084 { 3085 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2); 3086 } 3087 3088 // returns results in whatever encoding you request... but note that 2-byte encodings 3089 // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare 3090 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) 3091 { 3092 stbtt_int32 i,count,stringOffset; 3093 stbtt_uint8 *fc = font->data; 3094 stbtt_uint32 offset = font->fontstart; 3095 stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); 3096 if (!nm) return NULL; 3097 3098 count = ttUSHORT(fc+nm+2); 3099 stringOffset = nm + ttUSHORT(fc+nm+4); 3100 for (i=0; i < count; ++i) { 3101 stbtt_uint32 loc = nm + 6 + 12 * i; 3102 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) 3103 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { 3104 *length = ttUSHORT(fc+loc+8); 3105 return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); 3106 } 3107 } 3108 return NULL; 3109 } 3110 3111 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) 3112 { 3113 stbtt_int32 i; 3114 stbtt_int32 count = ttUSHORT(fc+nm+2); 3115 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); 3116 3117 for (i=0; i < count; ++i) { 3118 stbtt_uint32 loc = nm + 6 + 12 * i; 3119 stbtt_int32 id = ttUSHORT(fc+loc+6); 3120 if (id == target_id) { 3121 // find the encoding 3122 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); 3123 3124 // is this a Unicode encoding? 3125 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { 3126 stbtt_int32 slen = ttUSHORT(fc+loc+8); 3127 stbtt_int32 off = ttUSHORT(fc+loc+10); 3128 3129 // check if there's a prefix match 3130 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); 3131 if (matchlen >= 0) { 3132 // check for target_id+1 immediately following, with same encoding & language 3133 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) { 3134 slen = ttUSHORT(fc+loc+12+8); 3135 off = ttUSHORT(fc+loc+12+10); 3136 if (slen == 0) { 3137 if (matchlen == nlen) 3138 return 1; 3139 } else if (matchlen < nlen && name[matchlen] == ' ') { 3140 ++matchlen; 3141 if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) 3142 return 1; 3143 } 3144 } else { 3145 // if nothing immediately following 3146 if (matchlen == nlen) 3147 return 1; 3148 } 3149 } 3150 } 3151 3152 // @TODO handle other encodings 3153 } 3154 } 3155 return 0; 3156 } 3157 3158 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) 3159 { 3160 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); 3161 stbtt_uint32 nm,hd; 3162 if (!stbtt__isfont(fc+offset)) return 0; 3163 3164 // check italics/bold/underline flags in macStyle... 3165 if (flags) { 3166 hd = stbtt__find_table(fc, offset, "head"); 3167 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; 3168 } 3169 3170 nm = stbtt__find_table(fc, offset, "name"); 3171 if (!nm) return 0; 3172 3173 if (flags) { 3174 // if we checked the macStyle flags, then just check the family and ignore the subfamily 3175 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; 3176 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; 3177 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; 3178 } else { 3179 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; 3180 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; 3181 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; 3182 } 3183 3184 return 0; 3185 } 3186 3187 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) 3188 { 3189 stbtt_int32 i; 3190 for (i=0;;++i) { 3191 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); 3192 if (off < 0) return off; 3193 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) 3194 return off; 3195 } 3196 } 3197 3198 #endif // STB_TRUETYPE_IMPLEMENTATION 3199 3200 3201 // FULL VERSION HISTORY 3202 // 3203 // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges 3204 // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; 3205 // allow PackFontRanges to pack and render in separate phases; 3206 // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); 3207 // fixed an assert() bug in the new rasterizer 3208 // replace assert() with STBTT_assert() in new rasterizer 3209 // 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) 3210 // also more precise AA rasterizer, except if shapes overlap 3211 // remove need for STBTT_sort 3212 // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC 3213 // 1.04 (2015-04-15) typo in example 3214 // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes 3215 // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ 3216 // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match 3217 // non-oversampled; STBTT_POINT_SIZE for packed case only 3218 // 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling 3219 // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) 3220 // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID 3221 // 0.8b (2014-07-07) fix a warning 3222 // 0.8 (2014-05-25) fix a few more warnings 3223 // 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back 3224 // 0.6c (2012-07-24) improve documentation 3225 // 0.6b (2012-07-20) fix a few more warnings 3226 // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, 3227 // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty 3228 // 0.5 (2011-12-09) bugfixes: 3229 // subpixel glyph renderer computed wrong bounding box 3230 // first vertex of shape can be off-curve (FreeSans) 3231 // 0.4b (2011-12-03) fixed an error in the font baking example 3232 // 0.4 (2011-12-01) kerning, subpixel rendering (tor) 3233 // bugfixes for: 3234 // codepoint-to-glyph conversion using table fmt=12 3235 // codepoint-to-glyph conversion using table fmt=4 3236 // stbtt_GetBakedQuad with non-square texture (Zer) 3237 // updated Hello World! sample to use kerning and subpixel 3238 // fixed some warnings 3239 // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) 3240 // userdata, malloc-from-userdata, non-zero fill (stb) 3241 // 0.2 (2009-03-11) Fix unsigned/signed char warnings 3242 // 0.1 (2009-03-09) First public release 3243 // 3244