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