Changeset e66fd66 in opengl-game for IMGUI/imstb_truetype.h
- Timestamp:
- Dec 5, 2020, 7:14:31 PM (4 years ago)
- Branches:
- feature/imgui-sdl, master
- Children:
- 95c657f
- Parents:
- 78c3045
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
IMGUI/imstb_truetype.h
r78c3045 re66fd66 1 // stb_truetype.h - v1.19 - public domain 1 // [DEAR IMGUI] 2 // This is a slightly modified version of stb_truetype.h 1.20. 3 // Mostly fixing for compiler and static analyzer warnings. 4 // Grep for [DEAR IMGUI] to find the changes. 5 6 // stb_truetype.h - v1.20 - public domain 2 7 // authored from 2009-2016 by Sean Barrett / RAD Game Tools 3 8 // … … 50 55 // VERSION HISTORY 51 56 // 57 // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() 52 58 // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod 53 59 // 1.18 (2018-01-29) add missing function … … 76 82 // USAGE 77 83 // 78 // Include this file in whatever places nee ed to refer to it. In ONE C/C++84 // Include this file in whatever places need to refer to it. In ONE C/C++ 79 85 // file, write: 80 86 // #define STB_TRUETYPE_IMPLEMENTATION … … 248 254 // Sample code 140 LOC / 249 255 // Truetype parsing 620 LOC ---- 620 LOC TrueType 250 // Software rasterization 240 LOC \ 251 // Curve tessel ation120 LOC \__ 550 LOC Bitmap creation256 // Software rasterization 240 LOC \. 257 // Curve tessellation 120 LOC \__ 550 LOC Bitmap creation 252 258 // Bitmap management 100 LOC / 253 259 // Baked bitmap interface 70 LOC / … … 276 282 #include "stb_truetype.h" 277 283 278 unsigned char ttf_buffer[1 <<20];279 unsigned char temp_bitmap[512 *512];284 unsigned char ttf_buffer[1<<20]; 285 unsigned char temp_bitmap[512*512]; 280 286 281 287 stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs … … 284 290 void my_stbtt_initfont(void) 285 291 { 286 fread(ttf_buffer, 1, 1 <<20, fopen("c:/windows/fonts/times.ttf", "rb"));287 stbtt_BakeFontBitmap(ttf_buffer, 0, 32.0, temp_bitmap, 512, 512, 32,96, cdata); // no guarantee this fits!288 292 fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); 293 stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits! 294 // can free ttf_buffer at this point 289 295 glGenTextures(1, &ftex); 290 296 glBindTexture(GL_TEXTURE_2D, ftex); 291 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512, 297 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); 292 298 // can free temp_bitmap at this point 293 299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); … … 303 309 if (*text >= 32 && *text < 128) { 304 310 stbtt_aligned_quad q; 305 stbtt_GetBakedQuad(cdata, 512, 512, *text - 32, &x, &y, &q,1);//1=opengl & d3d10+,0=d3d9306 glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0,q.y0);307 glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1,q.y0);308 glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1,q.y1);309 glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0,q.y1);311 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 312 glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); 313 glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); 314 glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); 315 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); 310 316 } 311 317 ++text; … … 325 331 #include "stb_truetype.h" 326 332 327 char ttf_buffer[1 <<25];333 char ttf_buffer[1<<25]; 328 334 329 335 int main(int argc, char **argv) … … 331 337 stbtt_fontinfo font; 332 338 unsigned char *bitmap; 333 int w, h, i, j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);334 335 fread(ttf_buffer, 1, 1 <<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));336 337 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer, 338 bitmap = stbtt_GetCodepointBitmap(&font, 0, stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);339 340 for (j =0; j < h; ++j) {341 for (i =0; i < w; ++i)342 putchar(" .:ioVM@"[bitmap[j*w + i] >>5]);339 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); 340 341 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); 342 343 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); 344 bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); 345 346 for (j=0; j < h; ++j) { 347 for (i=0; i < w; ++i) 348 putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); 343 349 putchar('\n'); 344 350 } … … 365 371 // 366 372 #if 0 367 char buffer[24 <<20];373 char buffer[24<<20]; 368 374 unsigned char screen[20][79]; 369 375 … … 371 377 { 372 378 stbtt_fontinfo font; 373 int i, j, ascent, baseline, ch =0;374 float scale, xpos =2; // leave a little padding in case the character extends left379 int i,j,ascent,baseline,ch=0; 380 float scale, xpos=2; // leave a little padding in case the character extends left 375 381 char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness 376 382 … … 379 385 380 386 scale = stbtt_ScaleForPixelHeight(&font, 15); 381 stbtt_GetFontVMetrics(&font, &ascent, 0,0);382 baseline = (int) (ascent*scale);387 stbtt_GetFontVMetrics(&font, &ascent,0,0); 388 baseline = (int) (ascent*scale); 383 389 384 390 while (text[ch]) { 385 int advance, lsb, x0, y0, x1,y1;386 float x_shift = xpos - (float) floor(xpos);391 int advance,lsb,x0,y0,x1,y1; 392 float x_shift = xpos - (float) floor(xpos); 387 393 stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); 388 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale, scale, x_shift, 0, &x0, &y0, &x1,&y1);389 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1 - x0, y1 - y0, 79, scale, scale, x_shift,0, text[ch]);394 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); 395 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); 390 396 // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong 391 397 // because this API is really for baking character bitmaps into textures. if you want to render … … 393 399 // "alpha blend" that into the working buffer 394 400 xpos += (advance * scale); 395 if (text[ch +1])396 xpos += scale * stbtt_GetCodepointKernAdvance(&font, text[ch], text[ch +1]);401 if (text[ch+1]) 402 xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); 397 403 ++ch; 398 404 } 399 405 400 for (j =0; j < 20; ++j) {401 for (i =0; i < 78; ++i)402 putchar(" .:ioVM@"[screen[j][i] >>5]);406 for (j=0; j < 20; ++j) { 407 for (i=0; i < 78; ++i) 408 putchar(" .:ioVM@"[screen[j][i]>>5]); 403 409 putchar('\n'); 404 410 } … … 419 425 420 426 #ifdef STB_TRUETYPE_IMPLEMENTATION 421 // #define your own (u)stbtt_int8/16/32 before including to override this422 #ifndef stbtt_uint8423 typedef unsigned char stbtt_uint8;424 typedef signed char stbtt_int8;425 typedef unsigned short stbtt_uint16;426 typedef signed short stbtt_int16;427 typedef unsigned int stbtt_uint32;428 typedef signed int stbtt_int32;429 #endif430 431 typedef char stbtt__check_size32[sizeof(stbtt_int32) ==4 ? 1 : -1];432 typedef char stbtt__check_size16[sizeof(stbtt_int16) ==2 ? 1 : -1];433 434 // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h435 #ifndef STBTT_ifloor436 #include <math.h>437 #define STBTT_ifloor(x) ((int) floor(x))438 #define STBTT_iceil(x) ((int) ceil(x))439 #endif440 441 #ifndef STBTT_sqrt442 #include <math.h>443 #define STBTT_sqrt(x) sqrt(x)444 #define STBTT_pow(x,y) pow(x,y)445 #endif446 447 #ifndef STBTT_fmod448 #include <math.h>449 #define STBTT_fmod(x,y) fmod(x,y)450 #endif451 452 #ifndef STBTT_cos453 #include <math.h>454 #define STBTT_cos(x) cos(x)455 #define STBTT_acos(x) acos(x)456 #endif457 458 #ifndef STBTT_fabs459 #include <math.h>460 #define STBTT_fabs(x) fabs(x)461 #endif462 463 // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h464 #ifndef STBTT_malloc465 #include <stdlib.h>466 #define STBTT_malloc(x,u) ((void)(u),malloc(x))467 #define STBTT_free(x,u) ((void)(u),free(x))468 #endif469 470 #ifndef STBTT_assert471 #include <assert.h>472 #define STBTT_assert(x) assert(x)473 #endif474 475 #ifndef STBTT_strlen476 #include <string.h>477 #define STBTT_strlen(x) strlen(x)478 #endif479 480 #ifndef STBTT_memcpy481 #include <string.h>482 #define STBTT_memcpy memcpy483 #define STBTT_memset memset484 #endif427 // #define your own (u)stbtt_int8/16/32 before including to override this 428 #ifndef stbtt_uint8 429 typedef unsigned char stbtt_uint8; 430 typedef signed char stbtt_int8; 431 typedef unsigned short stbtt_uint16; 432 typedef signed short stbtt_int16; 433 typedef unsigned int stbtt_uint32; 434 typedef signed int stbtt_int32; 435 #endif 436 437 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; 438 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; 439 440 // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h 441 #ifndef STBTT_ifloor 442 #include <math.h> 443 #define STBTT_ifloor(x) ((int) floor(x)) 444 #define STBTT_iceil(x) ((int) ceil(x)) 445 #endif 446 447 #ifndef STBTT_sqrt 448 #include <math.h> 449 #define STBTT_sqrt(x) sqrt(x) 450 #define STBTT_pow(x,y) pow(x,y) 451 #endif 452 453 #ifndef STBTT_fmod 454 #include <math.h> 455 #define STBTT_fmod(x,y) fmod(x,y) 456 #endif 457 458 #ifndef STBTT_cos 459 #include <math.h> 460 #define STBTT_cos(x) cos(x) 461 #define STBTT_acos(x) acos(x) 462 #endif 463 464 #ifndef STBTT_fabs 465 #include <math.h> 466 #define STBTT_fabs(x) fabs(x) 467 #endif 468 469 // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h 470 #ifndef STBTT_malloc 471 #include <stdlib.h> 472 #define STBTT_malloc(x,u) ((void)(u),malloc(x)) 473 #define STBTT_free(x,u) ((void)(u),free(x)) 474 #endif 475 476 #ifndef STBTT_assert 477 #include <assert.h> 478 #define STBTT_assert(x) assert(x) 479 #endif 480 481 #ifndef STBTT_strlen 482 #include <string.h> 483 #define STBTT_strlen(x) strlen(x) 484 #endif 485 486 #ifndef STBTT_memcpy 487 #include <string.h> 488 #define STBTT_memcpy memcpy 489 #define STBTT_memset memset 490 #endif 485 491 #endif 486 492 … … 505 511 #endif 506 512 507 // private structure 508 typedef struct 509 { 510 unsigned char *data; 511 int cursor; 512 int size; 513 } stbtt__buf; 514 515 ////////////////////////////////////////////////////////////////////////////// 516 // 517 // TEXTURE BAKING API 518 // 519 // If you use this API, you only have to call two functions ever. 520 // 521 522 typedef struct 523 { 524 unsigned short x0, y0, x1, y1; // coordinates of bbox in bitmap 525 float xoff, yoff, xadvance; 526 } stbtt_bakedchar; 527 528 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) 529 float pixel_height, // height of font in pixels 530 unsigned char *pixels, int pw, int ph, // bitmap to be filled in 531 int first_char, int num_chars, // characters to bake 532 stbtt_bakedchar *chardata); // you allocate this, it's num_chars long 533 // if return is positive, the first unused row of the bitmap 534 // if return is negative, returns the negative of the number of characters that fit 535 // if return is 0, no characters fit and no rows were used 536 // This uses a very crappy packing. 537 538 typedef struct 539 { 540 float x0, y0, s0, t0; // top-left 541 float x1, y1, s1, t1; // bottom-right 542 } stbtt_aligned_quad; 543 544 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above 545 int char_index, // character to display 546 float *xpos, float *ypos, // pointers to current position in screen pixel space 547 stbtt_aligned_quad *q, // output: quad to draw 548 int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier 549 // Call GetBakedQuad with char_index = 'character - first_char', and it 550 // creates the quad you need to draw and advances the current position. 551 // 552 // The coordinate system used assumes y increases downwards. 553 // 554 // Characters will extend both above and below the current position; 555 // see discussion of "BASELINE" above. 556 // 557 // It's inefficient; you might want to c&p it and optimize it. 558 559 560 561 ////////////////////////////////////////////////////////////////////////////// 562 // 563 // NEW TEXTURE BAKING API 564 // 565 // This provides options for packing multiple fonts into one atlas, not 566 // perfectly but better than nothing. 567 568 typedef struct 569 { 570 unsigned short x0, y0, x1, y1; // coordinates of bbox in bitmap 571 float xoff, yoff, xadvance; 572 float xoff2, yoff2; 573 } stbtt_packedchar; 574 575 typedef struct stbtt_pack_context stbtt_pack_context; 576 typedef struct stbtt_fontinfo stbtt_fontinfo; 513 // private structure 514 typedef struct 515 { 516 unsigned char *data; 517 int cursor; 518 int size; 519 } stbtt__buf; 520 521 ////////////////////////////////////////////////////////////////////////////// 522 // 523 // TEXTURE BAKING API 524 // 525 // If you use this API, you only have to call two functions ever. 526 // 527 528 typedef struct 529 { 530 unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap 531 float xoff,yoff,xadvance; 532 } stbtt_bakedchar; 533 534 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) 535 float pixel_height, // height of font in pixels 536 unsigned char *pixels, int pw, int ph, // bitmap to be filled in 537 int first_char, int num_chars, // characters to bake 538 stbtt_bakedchar *chardata); // you allocate this, it's num_chars long 539 // if return is positive, the first unused row of the bitmap 540 // if return is negative, returns the negative of the number of characters that fit 541 // if return is 0, no characters fit and no rows were used 542 // This uses a very crappy packing. 543 544 typedef struct 545 { 546 float x0,y0,s0,t0; // top-left 547 float x1,y1,s1,t1; // bottom-right 548 } stbtt_aligned_quad; 549 550 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above 551 int char_index, // character to display 552 float *xpos, float *ypos, // pointers to current position in screen pixel space 553 stbtt_aligned_quad *q, // output: quad to draw 554 int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier 555 // Call GetBakedQuad with char_index = 'character - first_char', and it 556 // creates the quad you need to draw and advances the current position. 557 // 558 // The coordinate system used assumes y increases downwards. 559 // 560 // Characters will extend both above and below the current position; 561 // see discussion of "BASELINE" above. 562 // 563 // It's inefficient; you might want to c&p it and optimize it. 564 565 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); 566 // Query the font vertical metrics without having to create a font first. 567 568 569 ////////////////////////////////////////////////////////////////////////////// 570 // 571 // NEW TEXTURE BAKING API 572 // 573 // This provides options for packing multiple fonts into one atlas, not 574 // perfectly but better than nothing. 575 576 typedef struct 577 { 578 unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap 579 float xoff,yoff,xadvance; 580 float xoff2,yoff2; 581 } stbtt_packedchar; 582 583 typedef struct stbtt_pack_context stbtt_pack_context; 584 typedef struct stbtt_fontinfo stbtt_fontinfo; 577 585 #ifndef STB_RECT_PACK_VERSION 578 586 typedef struct stbrp_rect stbrp_rect; 579 587 #endif 580 588 581 582 583 584 585 586 587 588 589 590 591 592 STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc);593 589 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); 590 // Initializes a packing context stored in the passed-in stbtt_pack_context. 591 // Future calls using this context will pack characters into the bitmap passed 592 // in here: a 1-channel bitmap that is width * height. stride_in_bytes is 593 // the distance from one row to the next (or 0 to mean they are packed tightly 594 // together). "padding" is the amount of padding to leave between each 595 // character (normally you want '1' for bitmaps you'll use as textures with 596 // bilinear filtering). 597 // 598 // Returns 0 on failure, 1 on success. 599 600 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); 601 // Cleans up the packing context and frees all memory. 594 602 595 603 #define STBTT_POINT_SIZE(x) (-(x)) 596 604 597 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, 598 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); 599 // Creates character bitmaps from the font_index'th font found in fontdata (use 600 // font_index=0 if you don't know what that is). It creates num_chars_in_range 601 // bitmaps for characters with unicode values starting at first_unicode_char_in_range 602 // and increasing. Data for how to render them is stored in chardata_for_range; 603 // pass these to stbtt_GetPackedQuad to get back renderable quads. 604 // 605 // font_size is the full height of the character from ascender to descender, 606 // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed 607 // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() 608 // and pass that result as 'font_size': 609 // ..., 20 , ... // font max minus min y is 20 pixels tall 610 // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall 611 612 typedef struct 613 { 614 float font_size; 615 int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint 616 int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints 617 int num_chars; 618 stbtt_packedchar *chardata_for_range; // output 619 unsigned char h_oversample, v_oversample; // don't set these, they're used internally 620 } stbtt_pack_range; 621 622 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); 623 // Creates character bitmaps from multiple ranges of characters stored in 624 // ranges. This will usually create a better-packed bitmap than multiple 625 // calls to stbtt_PackFontRange. Note that you can call this multiple 626 // times within a single PackBegin/PackEnd. 627 628 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); 629 // Oversampling a font increases the quality by allowing higher-quality subpixel 630 // positioning, and is especially valuable at smaller text sizes. 631 // 632 // This function sets the amount of oversampling for all following calls to 633 // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given 634 // pack context. The default (no oversampling) is achieved by h_oversample=1 635 // and v_oversample=1. The total number of pixels required is 636 // h_oversample*v_oversample larger than the default; for example, 2x2 637 // oversampling requires 4x the storage of 1x1. For best results, render 638 // oversampled textures with bilinear filtering. Look at the readme in 639 // stb/tests/oversample for information about oversampled fonts 640 // 641 // To use with PackFontRangesGather etc., you must set it before calls 642 // call to PackFontRangesGatherRects. 643 644 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above 645 int char_index, // character to display 646 float *xpos, float *ypos, // pointers to current position in screen pixel space 647 stbtt_aligned_quad *q, // output: quad to draw 648 int align_to_integer); 649 650 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 651 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); 652 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 653 // Calling these functions in sequence is roughly equivalent to calling 654 // stbtt_PackFontRanges(). If you more control over the packing of multiple 655 // fonts, or if you want to pack custom data into a font texture, take a look 656 // at the source to of stbtt_PackFontRanges() and create a custom version 657 // using these functions, e.g. call GatherRects multiple times, 658 // building up a single array of rects, then call PackRects once, 659 // then call RenderIntoRects repeatedly. This may result in a 660 // better packing than calling PackFontRanges multiple times 661 // (or it may not). 662 663 // this is an opaque structure that you shouldn't mess with which holds 664 // all the context needed from PackBegin to PackEnd. 665 struct stbtt_pack_context { 666 void *user_allocator_context; 667 void *pack_info; 668 int width; 669 int height; 670 int stride_in_bytes; 671 int padding; 672 unsigned int h_oversample, v_oversample; 673 unsigned char *pixels; 674 void *nodes; 675 }; 676 677 ////////////////////////////////////////////////////////////////////////////// 678 // 679 // FONT LOADING 680 // 681 // 682 683 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); 684 // This function will determine the number of fonts in a font file. TrueType 685 // collection (.ttc) files may contain multiple fonts, while TrueType font 686 // (.ttf) files only contain one font. The number of fonts can be used for 687 // indexing with the previous function where the index is between zero and one 688 // less than the total fonts. If an error occurs, -1 is returned. 689 690 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); 691 // Each .ttf/.ttc file may have more than one font. Each font has a sequential 692 // index number starting from 0. Call this function to get the font offset for 693 // a given index; it returns -1 if the index is out of range. A regular .ttf 694 // file will only define one font and it always be at offset 0, so it will 695 // return '0' for index 0, and -1 for all other indices. 696 697 // The following structure is defined publically so you can declare one on 698 // the stack or as a global or etc, but you should treat it as opaque. 699 struct stbtt_fontinfo 700 { 701 void * userdata; 702 unsigned char * data; // pointer to .ttf file 703 int fontstart; // offset of start of font 704 705 int numGlyphs; // number of glyphs, needed for range checking 706 707 int loca, head, glyf, hhea, hmtx, kern, gpos; // table locations as offset from start of .ttf 708 int index_map; // a cmap mapping for our chosen character encoding 709 int indexToLocFormat; // format needed to map from glyph index to glyph 710 711 stbtt__buf cff; // cff font data 712 stbtt__buf charstrings; // the charstring index 713 stbtt__buf gsubrs; // global charstring subroutines index 714 stbtt__buf subrs; // private charstring subroutines index 715 stbtt__buf fontdicts; // array of font dicts 716 stbtt__buf fdselect; // map from glyph to fontdict 717 }; 718 719 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); 720 // Given an offset into the file that defines a font, this function builds 721 // the necessary cached info for the rest of the system. You must allocate 722 // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't 723 // need to do anything special to free it, because the contents are pure 724 // value data with no additional data structures. Returns 0 on failure. 725 726 727 ////////////////////////////////////////////////////////////////////////////// 728 // 729 // CHARACTER TO GLYPH-INDEX CONVERSIOn 730 731 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); 732 // If you're going to perform multiple operations on the same character 733 // and you want a speed-up, call this function with the character you're 734 // going to process, then use glyph-based functions instead of the 735 // codepoint-based functions. 736 737 738 ////////////////////////////////////////////////////////////////////////////// 739 // 740 // CHARACTER PROPERTIES 741 // 742 743 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); 744 // computes a scale factor to produce a font whose "height" is 'pixels' tall. 745 // Height is measured as the distance from the highest ascender to the lowest 746 // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics 747 // and computing: 748 // scale = pixels / (ascent - descent) 749 // so if you prefer to measure height by the ascent only, use a similar calculation. 750 751 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); 752 // computes a scale factor to produce a font whose EM size is mapped to 753 // 'pixels' tall. This is probably what traditional APIs compute, but 754 // I'm not positive. 755 756 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); 757 // ascent is the coordinate above the baseline the font extends; descent 758 // is the coordinate below the baseline the font extends (i.e. it is typically negative) 759 // lineGap is the spacing between one row's descent and the next row's ascent... 760 // so you should advance the vertical position by "*ascent - *descent + *lineGap" 761 // these are expressed in unscaled coordinates, so you must multiply by 762 // the scale factor for a given size 763 764 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); 765 // analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 766 // table (specific to MS/Windows TTF files). 767 // 768 // Returns 1 on success (table present), 0 on failure. 769 770 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); 771 // the bounding box around all possible characters 772 773 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); 774 // leftSideBearing is the offset from the current horizontal position to the left edge of the character 775 // advanceWidth is the offset from the current horizontal position to the next horizontal position 776 // these are expressed in unscaled coordinates 777 778 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); 779 // an additional amount to add to the 'advance' value between ch1 and ch2 780 781 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); 782 // Gets the bounding box of the visible part of the glyph, in unscaled coordinates 783 784 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); 785 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); 786 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); 787 // as above, but takes one or more glyph indices for greater efficiency 788 789 790 ////////////////////////////////////////////////////////////////////////////// 791 // 792 // GLYPH SHAPES (you probably don't need these, but they have to go before 793 // the bitmaps for C declaration-order reasons) 794 // 605 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, 606 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); 607 // Creates character bitmaps from the font_index'th font found in fontdata (use 608 // font_index=0 if you don't know what that is). It creates num_chars_in_range 609 // bitmaps for characters with unicode values starting at first_unicode_char_in_range 610 // and increasing. Data for how to render them is stored in chardata_for_range; 611 // pass these to stbtt_GetPackedQuad to get back renderable quads. 612 // 613 // font_size is the full height of the character from ascender to descender, 614 // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed 615 // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() 616 // and pass that result as 'font_size': 617 // ..., 20 , ... // font max minus min y is 20 pixels tall 618 // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall 619 620 typedef struct 621 { 622 float font_size; 623 int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint 624 int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints 625 int num_chars; 626 stbtt_packedchar *chardata_for_range; // output 627 unsigned char h_oversample, v_oversample; // don't set these, they're used internally 628 } stbtt_pack_range; 629 630 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); 631 // Creates character bitmaps from multiple ranges of characters stored in 632 // ranges. This will usually create a better-packed bitmap than multiple 633 // calls to stbtt_PackFontRange. Note that you can call this multiple 634 // times within a single PackBegin/PackEnd. 635 636 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); 637 // Oversampling a font increases the quality by allowing higher-quality subpixel 638 // positioning, and is especially valuable at smaller text sizes. 639 // 640 // This function sets the amount of oversampling for all following calls to 641 // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given 642 // pack context. The default (no oversampling) is achieved by h_oversample=1 643 // and v_oversample=1. The total number of pixels required is 644 // h_oversample*v_oversample larger than the default; for example, 2x2 645 // oversampling requires 4x the storage of 1x1. For best results, render 646 // oversampled textures with bilinear filtering. Look at the readme in 647 // stb/tests/oversample for information about oversampled fonts 648 // 649 // To use with PackFontRangesGather etc., you must set it before calls 650 // call to PackFontRangesGatherRects. 651 652 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); 653 // If skip != 0, this tells stb_truetype to skip any codepoints for which 654 // there is no corresponding glyph. If skip=0, which is the default, then 655 // codepoints without a glyph recived the font's "missing character" glyph, 656 // typically an empty box by convention. 657 658 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above 659 int char_index, // character to display 660 float *xpos, float *ypos, // pointers to current position in screen pixel space 661 stbtt_aligned_quad *q, // output: quad to draw 662 int align_to_integer); 663 664 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 665 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); 666 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 667 // Calling these functions in sequence is roughly equivalent to calling 668 // stbtt_PackFontRanges(). If you more control over the packing of multiple 669 // fonts, or if you want to pack custom data into a font texture, take a look 670 // at the source to of stbtt_PackFontRanges() and create a custom version 671 // using these functions, e.g. call GatherRects multiple times, 672 // building up a single array of rects, then call PackRects once, 673 // then call RenderIntoRects repeatedly. This may result in a 674 // better packing than calling PackFontRanges multiple times 675 // (or it may not). 676 677 // this is an opaque structure that you shouldn't mess with which holds 678 // all the context needed from PackBegin to PackEnd. 679 struct stbtt_pack_context { 680 void *user_allocator_context; 681 void *pack_info; 682 int width; 683 int height; 684 int stride_in_bytes; 685 int padding; 686 int skip_missing; 687 unsigned int h_oversample, v_oversample; 688 unsigned char *pixels; 689 void *nodes; 690 }; 691 692 ////////////////////////////////////////////////////////////////////////////// 693 // 694 // FONT LOADING 695 // 696 // 697 698 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); 699 // This function will determine the number of fonts in a font file. TrueType 700 // collection (.ttc) files may contain multiple fonts, while TrueType font 701 // (.ttf) files only contain one font. The number of fonts can be used for 702 // indexing with the previous function where the index is between zero and one 703 // less than the total fonts. If an error occurs, -1 is returned. 704 705 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); 706 // Each .ttf/.ttc file may have more than one font. Each font has a sequential 707 // index number starting from 0. Call this function to get the font offset for 708 // a given index; it returns -1 if the index is out of range. A regular .ttf 709 // file will only define one font and it always be at offset 0, so it will 710 // return '0' for index 0, and -1 for all other indices. 711 712 // The following structure is defined publicly so you can declare one on 713 // the stack or as a global or etc, but you should treat it as opaque. 714 struct stbtt_fontinfo 715 { 716 void * userdata; 717 unsigned char * data; // pointer to .ttf file 718 int fontstart; // offset of start of font 719 720 int numGlyphs; // number of glyphs, needed for range checking 721 722 int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf 723 int index_map; // a cmap mapping for our chosen character encoding 724 int indexToLocFormat; // format needed to map from glyph index to glyph 725 726 stbtt__buf cff; // cff font data 727 stbtt__buf charstrings; // the charstring index 728 stbtt__buf gsubrs; // global charstring subroutines index 729 stbtt__buf subrs; // private charstring subroutines index 730 stbtt__buf fontdicts; // array of font dicts 731 stbtt__buf fdselect; // map from glyph to fontdict 732 }; 733 734 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); 735 // Given an offset into the file that defines a font, this function builds 736 // the necessary cached info for the rest of the system. You must allocate 737 // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't 738 // need to do anything special to free it, because the contents are pure 739 // value data with no additional data structures. Returns 0 on failure. 740 741 742 ////////////////////////////////////////////////////////////////////////////// 743 // 744 // CHARACTER TO GLYPH-INDEX CONVERSIOn 745 746 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); 747 // If you're going to perform multiple operations on the same character 748 // and you want a speed-up, call this function with the character you're 749 // going to process, then use glyph-based functions instead of the 750 // codepoint-based functions. 751 // Returns 0 if the character codepoint is not defined in the font. 752 753 754 ////////////////////////////////////////////////////////////////////////////// 755 // 756 // CHARACTER PROPERTIES 757 // 758 759 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); 760 // computes a scale factor to produce a font whose "height" is 'pixels' tall. 761 // Height is measured as the distance from the highest ascender to the lowest 762 // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics 763 // and computing: 764 // scale = pixels / (ascent - descent) 765 // so if you prefer to measure height by the ascent only, use a similar calculation. 766 767 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); 768 // computes a scale factor to produce a font whose EM size is mapped to 769 // 'pixels' tall. This is probably what traditional APIs compute, but 770 // I'm not positive. 771 772 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); 773 // ascent is the coordinate above the baseline the font extends; descent 774 // is the coordinate below the baseline the font extends (i.e. it is typically negative) 775 // lineGap is the spacing between one row's descent and the next row's ascent... 776 // so you should advance the vertical position by "*ascent - *descent + *lineGap" 777 // these are expressed in unscaled coordinates, so you must multiply by 778 // the scale factor for a given size 779 780 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); 781 // analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 782 // table (specific to MS/Windows TTF files). 783 // 784 // Returns 1 on success (table present), 0 on failure. 785 786 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); 787 // the bounding box around all possible characters 788 789 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); 790 // leftSideBearing is the offset from the current horizontal position to the left edge of the character 791 // advanceWidth is the offset from the current horizontal position to the next horizontal position 792 // these are expressed in unscaled coordinates 793 794 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); 795 // an additional amount to add to the 'advance' value between ch1 and ch2 796 797 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); 798 // Gets the bounding box of the visible part of the glyph, in unscaled coordinates 799 800 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); 801 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); 802 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); 803 // as above, but takes one or more glyph indices for greater efficiency 804 805 806 ////////////////////////////////////////////////////////////////////////////// 807 // 808 // GLYPH SHAPES (you probably don't need these, but they have to go before 809 // the bitmaps for C declaration-order reasons) 810 // 795 811 796 812 #ifndef STBTT_vmove // you can predefine these to use different values (but why?) 797 813 enum { 798 STBTT_vmove =1,814 STBTT_vmove=1, 799 815 STBTT_vline, 800 816 STBTT_vcurve, … … 804 820 805 821 #ifndef stbtt_vertex // you can predefine this to use different values 806 // (we share this with other code at RAD)807 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file822 // (we share this with other code at RAD) 823 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file 808 824 typedef struct 809 825 { 810 stbtt_vertex_type x, y, cx, cy, cx1,cy1;811 unsigned char type, 826 stbtt_vertex_type x,y,cx,cy,cx1,cy1; 827 unsigned char type,padding; 812 828 } stbtt_vertex; 813 829 #endif 814 830 815 816 817 818 819 820 821 822 823 // The shape is a series of countours. Each one starts with824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 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);888 889 890 891 892 893 int w, h,stride;894 895 896 897 898 899 float flatness_in_pixels, // allowable error of curve in pixels900 stbtt_vertex *vertices, // array of vertices defining shape901 int num_verts, // number of vertices in above array902 float scale_x, float scale_y, // scale applied to input vertices903 float shift_x, float shift_y, // translation applied to input vertices904 int x_off, int y_off, // another translation applied to input905 int invert, // if non-zero, vertically flip shape906 void *userdata); // context for to STBTT_MALLOC907 908 909 910 911 912 913 914 915 916 917 918 919 // larger than some threshhold to produce scalable fonts.920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 831 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); 832 // returns non-zero if nothing is drawn for this glyph 833 834 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); 835 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); 836 // returns # of vertices and fills *vertices with the pointer to them 837 // these are expressed in "unscaled" coordinates 838 // 839 // The shape is a series of contours. Each one starts with 840 // a STBTT_moveto, then consists of a series of mixed 841 // STBTT_lineto and STBTT_curveto segments. A lineto 842 // draws a line from previous endpoint to its x,y; a curveto 843 // draws a quadratic bezier from previous endpoint to 844 // its x,y, using cx,cy as the bezier control point. 845 846 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); 847 // frees the data allocated above 848 849 ////////////////////////////////////////////////////////////////////////////// 850 // 851 // BITMAP RENDERING 852 // 853 854 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); 855 // frees the bitmap allocated below 856 857 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); 858 // allocates a large-enough single-channel 8bpp bitmap and renders the 859 // specified character/glyph at the specified scale into it, with 860 // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). 861 // *width & *height are filled out with the width & height of the bitmap, 862 // which is stored left-to-right, top-to-bottom. 863 // 864 // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap 865 866 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); 867 // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel 868 // shift for the character 869 870 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); 871 // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap 872 // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap 873 // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the 874 // width and height and positioning info for it first. 875 876 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); 877 // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel 878 // shift for the character 879 880 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); 881 // same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering 882 // is performed (see stbtt_PackSetOversampling) 883 884 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); 885 // get the bbox of the bitmap centered around the glyph origin; so the 886 // bitmap width is ix1-ix0, height is iy1-iy0, and location to place 887 // the bitmap top left is (leftSideBearing*scale,iy0). 888 // (Note that the bitmap uses y-increases-down, but the shape uses 889 // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) 890 891 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); 892 // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel 893 // shift for the character 894 895 // the following functions are equivalent to the above functions, but operate 896 // on glyph indices instead of Unicode codepoints (for efficiency) 897 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); 898 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); 899 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); 900 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); 901 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); 902 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); 903 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); 904 905 906 // @TODO: don't expose this structure 907 typedef struct 908 { 909 int w,h,stride; 910 unsigned char *pixels; 911 } stbtt__bitmap; 912 913 // rasterize a shape with quadratic beziers into a bitmap 914 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into 915 float flatness_in_pixels, // allowable error of curve in pixels 916 stbtt_vertex *vertices, // array of vertices defining shape 917 int num_verts, // number of vertices in above array 918 float scale_x, float scale_y, // scale applied to input vertices 919 float shift_x, float shift_y, // translation applied to input vertices 920 int x_off, int y_off, // another translation applied to input 921 int invert, // if non-zero, vertically flip shape 922 void *userdata); // context for to STBTT_MALLOC 923 924 ////////////////////////////////////////////////////////////////////////////// 925 // 926 // Signed Distance Function (or Field) rendering 927 928 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); 929 // frees the SDF bitmap allocated below 930 931 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); 932 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); 933 // These functions compute a discretized SDF field for a single character, suitable for storing 934 // in a single-channel texture, sampling with bilinear filtering, and testing against 935 // larger than some threshold to produce scalable fonts. 936 // info -- the font 937 // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap 938 // glyph/codepoint -- the character to generate the SDF for 939 // padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), 940 // which allows effects like bit outlines 941 // onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) 942 // pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) 943 // if positive, > onedge_value is inside; if negative, < onedge_value is inside 944 // width,height -- output height & width of the SDF bitmap (including padding) 945 // xoff,yoff -- output origin of the character 946 // return value -- a 2D array of bytes 0..255, width*height in size 947 // 948 // pixel_dist_scale & onedge_value are a scale & bias that allows you to make 949 // optimal use of the limited 0..255 for your application, trading off precision 950 // and special effects. SDF values outside the range 0..255 are clamped to 0..255. 951 // 952 // Example: 953 // scale = stbtt_ScaleForPixelHeight(22) 954 // padding = 5 955 // onedge_value = 180 956 // pixel_dist_scale = 180/5.0 = 36.0 957 // 958 // This will create an SDF bitmap in which the character is about 22 pixels 959 // high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled 960 // shape, sample the SDF at each pixel and fill the pixel if the SDF value 961 // is greater than or equal to 180/255. (You'll actually want to antialias, 962 // which is beyond the scope of this example.) Additionally, you can compute 963 // offset outlines (e.g. to stroke the character border inside & outside, 964 // or only outside). For example, to fill outside the character up to 3 SDF 965 // pixels, you would compare against (180-36.0*3)/255 = 72/255. The above 966 // choice of variables maps a range from 5 pixels outside the shape to 967 // 2 pixels inside the shape to 0..255; this is intended primarily for apply 968 // outside effects only (the interior range is needed to allow proper 969 // antialiasing of the font at *smaller* sizes) 970 // 971 // The function computes the SDF analytically at each SDF pixel, not by e.g. 972 // building a higher-res bitmap and approximating it. In theory the quality 973 // should be as high as possible for an SDF of this size & representation, but 974 // unclear if this is true in practice (perhaps building a higher-res bitmap 975 // and computing from that can allow drop-out prevention). 976 // 977 // The algorithm has not been optimized at all, so expect it to be slow 978 // if computing lots of characters or very large sizes. 979 980 981 982 ////////////////////////////////////////////////////////////////////////////// 983 // 984 // Finding the right font... 985 // 986 // You should really just solve this offline, keep your own tables 987 // of what font is what, and don't try to get it out of the .ttf file. 988 // That's because getting it out of the .ttf file is really hard, because 989 // the names in the file can appear in many possible encodings, in many 990 // possible languages, and e.g. if you need a case-insensitive comparison, 991 // the details of that depend on the encoding & language in a complex way 992 // (actually underspecified in truetype, but also gigantic). 993 // 994 // But you can use the provided functions in two possible ways: 995 // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on 996 // unicode-encoded names to try to find the font you want; 997 // you can run this before calling stbtt_InitFont() 998 // 999 // stbtt_GetFontNameString() lets you get any of the various strings 1000 // from the file yourself and do your own comparisons on them. 1001 // You have to have called stbtt_InitFont() first. 1002 1003 1004 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); 1005 // returns the offset (not index) of the font that matches, or -1 if none 1006 // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". 1007 // if you use any other flag, use a font name like "Arial"; this checks 1008 // the 'macStyle' header field; i don't know if fonts set this consistently 993 1009 #define STBTT_MACSTYLE_DONTCARE 0 994 1010 #define STBTT_MACSTYLE_BOLD 1 … … 997 1013 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 998 1014 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 STBTT_PLATFORM_ID_UNICODE =0,1013 STBTT_PLATFORM_ID_MAC =1,1014 STBTT_PLATFORM_ID_ISO =2,1015 STBTT_PLATFORM_ID_MICROSOFT =31016 1017 1018 1019 STBTT_UNICODE_EID_UNICODE_1_0 =0,1020 STBTT_UNICODE_EID_UNICODE_1_1 =1,1021 STBTT_UNICODE_EID_ISO_10646 =2,1022 STBTT_UNICODE_EID_UNICODE_2_0_BMP =3,1023 STBTT_UNICODE_EID_UNICODE_2_0_FULL =41024 1025 1026 1027 STBTT_MS_EID_SYMBOL =0,1028 STBTT_MS_EID_UNICODE_BMP =1,1029 STBTT_MS_EID_SHIFTJIS =2,1030 STBTT_MS_EID_UNICODE_FULL =101031 1032 1033 1034 STBTT_MAC_EID_ROMAN = 0, STBTT_MAC_EID_ARABIC =4,1035 STBTT_MAC_EID_JAPANESE = 1, STBTT_MAC_EID_HEBREW =5,1036 STBTT_MAC_EID_CHINESE_TRAD = 2, STBTT_MAC_EID_GREEK =6,1037 STBTT_MAC_EID_KOREAN = 3, STBTT_MAC_EID_RUSSIAN =71038 1039 1040 1041 1042 STBTT_MS_LANG_ENGLISH = 0x0409, STBTT_MS_LANG_ITALIAN =0x0410,1043 STBTT_MS_LANG_CHINESE = 0x0804, STBTT_MS_LANG_JAPANESE =0x0411,1044 STBTT_MS_LANG_DUTCH = 0x0413, STBTT_MS_LANG_KOREAN =0x0412,1045 STBTT_MS_LANG_FRENCH = 0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,1046 STBTT_MS_LANG_GERMAN = 0x0407, STBTT_MS_LANG_SPANISH =0x0409,1047 STBTT_MS_LANG_HEBREW = 0x040d, STBTT_MS_LANG_SWEDISH =0x041D1048 1049 1050 1051 STBTT_MAC_LANG_ENGLISH = 0, STBTT_MAC_LANG_JAPANESE =11,1052 STBTT_MAC_LANG_ARABIC = 12, STBTT_MAC_LANG_KOREAN =23,1053 STBTT_MAC_LANG_DUTCH = 4, STBTT_MAC_LANG_RUSSIAN =32,1054 STBTT_MAC_LANG_FRENCH = 1, STBTT_MAC_LANG_SPANISH = 6,1055 STBTT_MAC_LANG_GERMAN = 2, STBTT_MAC_LANG_SWEDISH = 5,1056 STBTT_MAC_LANG_HEBREW = 10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,1057 STBTT_MAC_LANG_ITALIAN = 3, STBTT_MAC_LANG_CHINESE_TRAD =191058 1015 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); 1016 // returns 1/0 whether the first string interpreted as utf8 is identical to 1017 // the second string interpreted as big-endian utf16... useful for strings from next func 1018 1019 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); 1020 // returns the string (which may be big-endian double byte, e.g. for unicode) 1021 // and puts the length in bytes in *length. 1022 // 1023 // some of the values for the IDs are below; for more see the truetype spec: 1024 // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html 1025 // http://www.microsoft.com/typography/otspec/name.htm 1026 1027 enum { // platformID 1028 STBTT_PLATFORM_ID_UNICODE =0, 1029 STBTT_PLATFORM_ID_MAC =1, 1030 STBTT_PLATFORM_ID_ISO =2, 1031 STBTT_PLATFORM_ID_MICROSOFT =3 1032 }; 1033 1034 enum { // encodingID for STBTT_PLATFORM_ID_UNICODE 1035 STBTT_UNICODE_EID_UNICODE_1_0 =0, 1036 STBTT_UNICODE_EID_UNICODE_1_1 =1, 1037 STBTT_UNICODE_EID_ISO_10646 =2, 1038 STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, 1039 STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 1040 }; 1041 1042 enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT 1043 STBTT_MS_EID_SYMBOL =0, 1044 STBTT_MS_EID_UNICODE_BMP =1, 1045 STBTT_MS_EID_SHIFTJIS =2, 1046 STBTT_MS_EID_UNICODE_FULL =10 1047 }; 1048 1049 enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes 1050 STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, 1051 STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, 1052 STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, 1053 STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 1054 }; 1055 1056 enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... 1057 // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs 1058 STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, 1059 STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, 1060 STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, 1061 STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, 1062 STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, 1063 STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D 1064 }; 1065 1066 enum { // languageID for STBTT_PLATFORM_ID_MAC 1067 STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, 1068 STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, 1069 STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, 1070 STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , 1071 STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , 1072 STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, 1073 STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 1074 }; 1059 1075 1060 1076 #ifdef __cplusplus … … 1081 1097 #endif 1082 1098 1083 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE -1)) == 0 ? 1 : -1];1099 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; 1084 1100 1085 1101 #ifndef STBTT_RASTERIZER_VERSION … … 1137 1153 stbtt__buf r; 1138 1154 STBTT_assert(size < 0x40000000); 1139 r.data = (stbtt_uint8*) p;1140 r.size = (int) size;1155 r.data = (stbtt_uint8*) p; 1156 r.size = (int) size; 1141 1157 r.cursor = 0; 1142 1158 return r; … … 1173 1189 int b0 = stbtt__buf_get8(b); 1174 1190 if (b0 >= 32 && b0 <= 246) return b0 - 139; 1175 else if (b0 >= 247 && b0 <= 250) return (b0 - 247) *256 + stbtt__buf_get8(b) + 108;1176 else if (b0 >= 251 && b0 <= 254) return -(b0 - 251) *256 - stbtt__buf_get8(b) - 108;1191 else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; 1192 else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; 1177 1193 else if (b0 == 28) return stbtt__buf_get16(b); 1178 1194 else if (b0 == 29) return stbtt__buf_get32(b); … … 1191 1207 break; 1192 1208 } 1193 } 1194 else { 1209 } else { 1195 1210 stbtt__cff_int(b); 1196 1211 } … … 1207 1222 op = stbtt__buf_get8(b); 1208 1223 if (op == 12) op = stbtt__buf_get8(b) | 0x100; 1209 if (op == key) return stbtt__buf_range(b, start, end -start);1224 if (op == key) return stbtt__buf_range(b, start, end-start); 1210 1225 } 1211 1226 return stbtt__buf_range(b, 0, 0); … … 1237 1252 start = stbtt__buf_get(&b, offsize); 1238 1253 end = stbtt__buf_get(&b, offsize); 1239 return stbtt__buf_range(&b, 2 + (count + 1)*offsize +start, end - start);1254 return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); 1240 1255 } 1241 1256 … … 1252 1267 #define ttFixed(p) ttLONG(p) 1253 1268 1254 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0] *256 + p[1]; }1255 static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0] *256 + p[1]; }1256 static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0] << 24) + (p[1] << 16) + (p[2] <<8) + p[3]; }1257 static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0] << 24) + (p[1] << 16) + (p[2] <<8) + p[3]; }1269 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } 1270 static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } 1271 static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } 1272 static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } 1258 1273 1259 1274 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) … … 1263 1278 { 1264 1279 // check the version number 1265 if (stbtt_tag4(font, '1', 0, 0,0)) return 1; // TrueType 11280 if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 1266 1281 if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! 1267 1282 if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF 1268 if (stbtt_tag4(font, 0, 1, 0,0)) return 1; // OpenType 1.01283 if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 1269 1284 if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts 1270 1285 return 0; … … 1274 1289 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) 1275 1290 { 1276 stbtt_int32 num_tables = ttUSHORT(data + fontstart +4);1291 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); 1277 1292 stbtt_uint32 tabledir = fontstart + 12; 1278 1293 stbtt_int32 i; 1279 for (i =0; i < num_tables; ++i) {1280 stbtt_uint32 loc = tabledir + 16 *i;1281 if (stbtt_tag(data + loc +0, tag))1282 return ttULONG(data + loc +8);1294 for (i=0; i < num_tables; ++i) { 1295 stbtt_uint32 loc = tabledir + 16*i; 1296 if (stbtt_tag(data+loc+0, tag)) 1297 return ttULONG(data+loc+8); 1283 1298 } 1284 1299 return 0; … … 1294 1309 if (stbtt_tag(font_collection, "ttcf")) { 1295 1310 // version 1? 1296 if (ttULONG(font_collection + 4) == 0x00010000 || ttULONG(font_collection +4) == 0x00020000) {1297 stbtt_int32 n = ttLONG(font_collection +8);1311 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { 1312 stbtt_int32 n = ttLONG(font_collection+8); 1298 1313 if (index >= n) 1299 1314 return -1; 1300 return ttULONG(font_collection + 12 + index *4);1315 return ttULONG(font_collection+12+index*4); 1301 1316 } 1302 1317 } … … 1313 1328 if (stbtt_tag(font_collection, "ttcf")) { 1314 1329 // version 1? 1315 if (ttULONG(font_collection + 4) == 0x00010000 || ttULONG(font_collection +4) == 0x00020000) {1316 return ttLONG(font_collection +8);1330 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { 1331 return ttLONG(font_collection+8); 1317 1332 } 1318 1333 } … … 1329 1344 stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); 1330 1345 if (!subrsoff) return stbtt__new_buf(NULL, 0); 1331 stbtt__buf_seek(&cff, private_loc[1] +subrsoff);1346 stbtt__buf_seek(&cff, private_loc[1]+subrsoff); 1332 1347 return stbtt__cff_get_index(&cff); 1333 1348 } … … 1336 1351 { 1337 1352 stbtt_uint32 cmap, t; 1338 stbtt_int32 i, 1353 stbtt_int32 i,numTables; 1339 1354 1340 1355 info->data = data; … … 1356 1371 // required for truetype 1357 1372 if (!info->loca) return 0; 1358 } 1359 else { 1373 } else { 1360 1374 // initialization for CFF / Type2 fonts (OTF) 1361 1375 stbtt__buf b, topdict, topdictidx; … … 1370 1384 1371 1385 // @TODO this should use size from table (not 512MB) 1372 info->cff = stbtt__new_buf(data + cff, 512 * 1024 *1024);1386 info->cff = stbtt__new_buf(data+cff, 512*1024*1024); 1373 1387 b = info->cff; 1374 1388 … … 1377 1391 stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize 1378 1392 1379 1380 1393 // @TODO the name INDEX could list multiple fonts, 1394 // but we just use the first one. 1381 1395 stbtt__cff_get_index(&b); // name INDEX 1382 1396 topdictidx = stbtt__cff_get_index(&b); … … 1400 1414 stbtt__buf_seek(&b, fdarrayoff); 1401 1415 info->fontdicts = stbtt__cff_get_index(&b); 1402 info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size -fdselectoff);1416 info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); 1403 1417 } 1404 1418 … … 1409 1423 t = stbtt__find_table(data, fontstart, "maxp"); 1410 1424 if (t) 1411 info->numGlyphs = ttUSHORT(data + t +4);1425 info->numGlyphs = ttUSHORT(data+t+4); 1412 1426 else 1413 1427 info->numGlyphs = 0xffff; … … 1418 1432 numTables = ttUSHORT(data + cmap + 2); 1419 1433 info->index_map = 0; 1420 for (i =0; i < numTables; ++i) {1434 for (i=0; i < numTables; ++i) { 1421 1435 stbtt_uint32 encoding_record = cmap + 4 + 8 * i; 1422 1436 // find an encoding we understand: 1423 switch (ttUSHORT(data + encoding_record)) { 1424 case STBTT_PLATFORM_ID_MICROSOFT: 1425 switch (ttUSHORT(data + encoding_record + 2)) { 1426 case STBTT_MS_EID_UNICODE_BMP: 1427 case STBTT_MS_EID_UNICODE_FULL: 1428 // MS/Unicode 1429 info->index_map = cmap + ttULONG(data + encoding_record + 4); 1437 switch(ttUSHORT(data+encoding_record)) { 1438 case STBTT_PLATFORM_ID_MICROSOFT: 1439 switch (ttUSHORT(data+encoding_record+2)) { 1440 case STBTT_MS_EID_UNICODE_BMP: 1441 case STBTT_MS_EID_UNICODE_FULL: 1442 // MS/Unicode 1443 info->index_map = cmap + ttULONG(data+encoding_record+4); 1444 break; 1445 } 1430 1446 break; 1431 } 1432 break; 1433 case STBTT_PLATFORM_ID_UNICODE: 1434 // Mac/iOS has these 1435 // all the encodingIDs are unicode, so we don't bother to check it 1436 info->index_map = cmap + ttULONG(data + encoding_record + 4); 1437 break; 1447 case STBTT_PLATFORM_ID_UNICODE: 1448 // Mac/iOS has these 1449 // all the encodingIDs are unicode, so we don't bother to check it 1450 info->index_map = cmap + ttULONG(data+encoding_record+4); 1451 break; 1438 1452 } 1439 1453 } … … 1441 1455 return 0; 1442 1456 1443 info->indexToLocFormat = ttUSHORT(data +info->head + 50);1457 info->indexToLocFormat = ttUSHORT(data+info->head + 50); 1444 1458 return 1; 1445 1459 } … … 1453 1467 if (format == 0) { // apple byte encoding 1454 1468 stbtt_int32 bytes = ttUSHORT(data + index_map + 2); 1455 if (unicode_codepoint < bytes -6)1469 if (unicode_codepoint < bytes-6) 1456 1470 return ttBYTE(data + index_map + 6 + unicode_codepoint); 1457 1471 return 0; 1458 } 1459 else if (format == 6) { 1472 } else if (format == 6) { 1460 1473 stbtt_uint32 first = ttUSHORT(data + index_map + 6); 1461 1474 stbtt_uint32 count = ttUSHORT(data + index_map + 8); 1462 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32)unicode_codepoint < first +count)1463 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first) *2);1475 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) 1476 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); 1464 1477 return 0; 1465 } 1466 else if (format == 2) { 1478 } else if (format == 2) { 1467 1479 STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean 1468 1480 return 0; 1469 } 1470 else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges 1471 stbtt_uint16 segcount = ttUSHORT(data + index_map + 6) >> 1; 1472 stbtt_uint16 searchRange = ttUSHORT(data + index_map + 8) >> 1; 1473 stbtt_uint16 entrySelector = ttUSHORT(data + index_map + 10); 1474 stbtt_uint16 rangeShift = ttUSHORT(data + index_map + 12) >> 1; 1481 } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges 1482 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; 1483 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; 1484 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); 1485 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; 1475 1486 1476 1487 // do a binary search of the segments … … 1483 1494 // they lie from endCount .. endCount + segCount 1484 1495 // but searchRange is the nearest power of two, so... 1485 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift *2))1486 search += rangeShift *2;1496 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) 1497 search += rangeShift*2; 1487 1498 1488 1499 // now decrement to bias correctly to find smallest … … 1491 1502 stbtt_uint16 end; 1492 1503 searchRange >>= 1; 1493 end = ttUSHORT(data + search + searchRange *2);1504 end = ttUSHORT(data + search + searchRange*2); 1494 1505 if (unicode_codepoint > end) 1495 search += searchRange *2;1506 search += searchRange*2; 1496 1507 --entrySelector; 1497 1508 } … … 1500 1511 { 1501 1512 stbtt_uint16 offset, start; 1502 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);1503 1504 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2 *item));1505 start = ttUSHORT(data + index_map + 14 + segcount * 2 + 2 + 2 *item);1513 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); 1514 1515 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); 1516 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); 1506 1517 if (unicode_codepoint < start) 1507 1518 return 0; 1508 1519 1509 offset = ttUSHORT(data + index_map + 14 + segcount * 6 + 2 + 2 *item);1520 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); 1510 1521 if (offset == 0) 1511 return (stbtt_uint16)(unicode_codepoint + ttSHORT(data + index_map + 14 + segcount * 4 + 2 + 2 * item)); 1512 1513 return ttUSHORT(data + offset + (unicode_codepoint - start) * 2 + index_map + 14 + segcount * 6 + 2 + 2 * item); 1514 } 1515 } 1516 else if (format == 12 || format == 13) { 1517 stbtt_uint32 ngroups = ttULONG(data + index_map + 12); 1518 stbtt_int32 low, high; 1522 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); 1523 1524 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); 1525 } 1526 } else if (format == 12 || format == 13) { 1527 stbtt_uint32 ngroups = ttULONG(data+index_map+12); 1528 stbtt_int32 low,high; 1519 1529 low = 0; high = (stbtt_int32)ngroups; 1520 1530 // Binary search the right group. 1521 1531 while (low < high) { 1522 stbtt_int32 mid = low + ((high -low) >> 1); // rounds down, so low <= mid < high1523 stbtt_uint32 start_char = ttULONG(data + index_map + 16 + mid *12);1524 stbtt_uint32 end_char = ttULONG(data + index_map + 16 + mid * 12 +4);1525 if ((stbtt_uint32) unicode_codepoint < start_char)1532 stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high 1533 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); 1534 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); 1535 if ((stbtt_uint32) unicode_codepoint < start_char) 1526 1536 high = mid; 1527 else if ((stbtt_uint32) unicode_codepoint > end_char)1528 low = mid +1;1537 else if ((stbtt_uint32) unicode_codepoint > end_char) 1538 low = mid+1; 1529 1539 else { 1530 stbtt_uint32 start_glyph = ttULONG(data + index_map + 16 + mid * 12 +8);1540 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); 1531 1541 if (format == 12) 1532 return start_glyph + unicode_codepoint -start_char;1542 return start_glyph + unicode_codepoint-start_char; 1533 1543 else // format == 13 1534 1544 return start_glyph; … … 1550 1560 { 1551 1561 v->type = type; 1552 v->x = (stbtt_int16) x;1553 v->y = (stbtt_int16) y;1554 v->cx = (stbtt_int16) cx;1555 v->cy = (stbtt_int16) cy;1562 v->x = (stbtt_int16) x; 1563 v->y = (stbtt_int16) y; 1564 v->cx = (stbtt_int16) cx; 1565 v->cy = (stbtt_int16) cy; 1556 1566 } 1557 1567 1558 1568 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) 1559 1569 { 1560 int g1, 1570 int g1,g2; 1561 1571 1562 1572 STBTT_assert(!info->cff.size); … … 1568 1578 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; 1569 1579 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; 1570 } 1571 else { 1572 g1 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4); 1573 g2 = info->glyf + ttULONG(info->data + info->loca + glyph_index * 4 + 4); 1574 } 1575 1576 return g1 == g2 ? -1 : g1; // if length is 0, return -1 1580 } else { 1581 g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); 1582 g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); 1583 } 1584 1585 return g1==g2 ? -1 : g1; // if length is 0, return -1 1577 1586 } 1578 1587 … … 1583 1592 if (info->cff.size) { 1584 1593 stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); 1585 } 1586 else { 1594 } else { 1587 1595 int g = stbtt__GetGlyfOffset(info, glyph_index); 1588 1596 if (g < 0) return 0; … … 1598 1606 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) 1599 1607 { 1600 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info, codepoint), x0, y0, x1,y1);1608 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); 1601 1609 } 1602 1610 … … 1614 1622 1615 1623 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, 1616 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)1624 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) 1617 1625 { 1618 1626 if (start_off) { 1619 1627 if (was_off) 1620 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx + scx) >> 1, (cy + scy) >> 1, cx, cy); 1621 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, scx, scy); 1622 } 1623 else { 1628 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); 1629 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); 1630 } else { 1624 1631 if (was_off) 1625 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx, sy, cx,cy);1632 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); 1626 1633 else 1627 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, sx, sy, 0,0);1634 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); 1628 1635 } 1629 1636 return num_vertices; … … 1635 1642 stbtt_uint8 *endPtsOfContours; 1636 1643 stbtt_uint8 *data = info->data; 1637 stbtt_vertex *vertices =0;1638 int num_vertices =0;1644 stbtt_vertex *vertices=0; 1645 int num_vertices=0; 1639 1646 int g = stbtt__GetGlyfOffset(info, glyph_index); 1640 1647 … … 1646 1653 1647 1654 if (numberOfContours > 0) { 1648 stbtt_uint8 flags = 0,flagcount;1649 stbtt_int32 ins, i, j = 0, m, n, next_move, was_off = 0, off, start_off =0;1650 stbtt_int32 x, y, cx, cy, sx, sy, scx,scy;1655 stbtt_uint8 flags=0,flagcount; 1656 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; 1657 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; 1651 1658 stbtt_uint8 *points; 1652 1659 endPtsOfContours = (data + g + 10); … … 1654 1661 points = data + g + 10 + numberOfContours * 2 + 2 + ins; 1655 1662 1656 n = 1 + ttUSHORT(endPtsOfContours + numberOfContours * 2 -2);1657 1658 m = n + 2 *numberOfContours; // a loose bound on how many vertices we might need1659 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);1663 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); 1664 1665 m = n + 2*numberOfContours; // a loose bound on how many vertices we might need 1666 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); 1660 1667 if (vertices == 0) 1661 1668 return 0; 1662 1669 1663 1670 next_move = 0; 1664 flagcount =0;1671 flagcount=0; 1665 1672 1666 1673 // in first pass, we load uninterpreted data into the allocated array … … 1670 1677 off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated 1671 1678 1672 1673 1674 for (i =0; i < n; ++i) {1679 // first load flags 1680 1681 for (i=0; i < n; ++i) { 1675 1682 if (flagcount == 0) { 1676 1683 flags = *points++; 1677 1684 if (flags & 8) 1678 1685 flagcount = *points++; 1679 } 1680 else 1686 } else 1681 1687 --flagcount; 1682 vertices[off +i].type = flags;1688 vertices[off+i].type = flags; 1683 1689 } 1684 1690 1685 1691 // now load x coordinates 1686 x =0;1687 for (i =0; i < n; ++i) {1688 flags = vertices[off +i].type;1692 x=0; 1693 for (i=0; i < n; ++i) { 1694 flags = vertices[off+i].type; 1689 1695 if (flags & 2) { 1690 1696 stbtt_int16 dx = *points++; 1691 1697 x += (flags & 16) ? dx : -dx; // ??? 1692 } 1693 else { 1698 } else { 1694 1699 if (!(flags & 16)) { 1695 x = x + (stbtt_int16) (points[0] *256 + points[1]);1700 x = x + (stbtt_int16) (points[0]*256 + points[1]); 1696 1701 points += 2; 1697 1702 } 1698 1703 } 1699 vertices[off + i].x = (stbtt_int16)x;1704 vertices[off+i].x = (stbtt_int16) x; 1700 1705 } 1701 1706 1702 1707 // now load y coordinates 1703 y =0;1704 for (i =0; i < n; ++i) {1705 flags = vertices[off +i].type;1708 y=0; 1709 for (i=0; i < n; ++i) { 1710 flags = vertices[off+i].type; 1706 1711 if (flags & 4) { 1707 1712 stbtt_int16 dy = *points++; 1708 1713 y += (flags & 32) ? dy : -dy; // ??? 1709 } 1710 else { 1714 } else { 1711 1715 if (!(flags & 32)) { 1712 y = y + (stbtt_int16) (points[0] *256 + points[1]);1716 y = y + (stbtt_int16) (points[0]*256 + points[1]); 1713 1717 points += 2; 1714 1718 } 1715 1719 } 1716 vertices[off + i].y = (stbtt_int16)y;1720 vertices[off+i].y = (stbtt_int16) y; 1717 1721 } 1718 1722 1719 1723 // now convert them to our format 1720 num_vertices =0;1724 num_vertices=0; 1721 1725 sx = sy = cx = cy = scx = scy = 0; 1722 for (i =0; i < n; ++i) {1723 flags = vertices[off +i].type;1724 x = (stbtt_int16)vertices[off +i].x;1725 y = (stbtt_int16)vertices[off +i].y;1726 for (i=0; i < n; ++i) { 1727 flags = vertices[off+i].type; 1728 x = (stbtt_int16) vertices[off+i].x; 1729 y = (stbtt_int16) vertices[off+i].y; 1726 1730 1727 1731 if (next_move == i) { 1728 1732 if (i != 0) 1729 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx, sy, scx, scy, cx,cy);1733 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 1730 1734 1731 1735 // now start the new one … … 1736 1740 scx = x; 1737 1741 scy = y; 1738 if (!(vertices[off + i +1].type & 1)) {1742 if (!(vertices[off+i+1].type & 1)) { 1739 1743 // next point is also a curve point, so interpolate an on-point curve 1740 sx = (x + (stbtt_int32)vertices[off + i + 1].x) >> 1; 1741 sy = (y + (stbtt_int32)vertices[off + i + 1].y) >> 1; 1742 } 1743 else { 1744 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; 1745 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; 1746 } else { 1744 1747 // otherwise just use the next point as our start point 1745 sx = (stbtt_int32) vertices[off + i +1].x;1746 sy = (stbtt_int32) vertices[off + i +1].y;1748 sx = (stbtt_int32) vertices[off+i+1].x; 1749 sy = (stbtt_int32) vertices[off+i+1].y; 1747 1750 ++i; // we're using point i+1 as the starting point, so skip it 1748 1751 } 1749 } 1750 else { 1752 } else { 1751 1753 sx = x; 1752 1754 sy = y; 1753 1755 } 1754 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove, sx, sy, 0,0);1756 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); 1755 1757 was_off = 0; 1756 next_move = 1 + ttUSHORT(endPtsOfContours + j *2);1758 next_move = 1 + ttUSHORT(endPtsOfContours+j*2); 1757 1759 ++j; 1758 } 1759 else { 1760 } else { 1760 1761 if (!(flags & 1)) { // if it's a curve 1761 1762 if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint 1762 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx + x) >> 1, (cy + y) >>1, cx, cy);1763 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); 1763 1764 cx = x; 1764 1765 cy = y; 1765 1766 was_off = 1; 1766 } 1767 else { 1767 } else { 1768 1768 if (was_off) 1769 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x, 1769 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); 1770 1770 else 1771 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x, y, 0,0);1771 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); 1772 1772 was_off = 0; 1773 1773 } 1774 1774 } 1775 1775 } 1776 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx, sy, scx, scy, cx, cy); 1777 } 1778 else if (numberOfContours == -1) { 1776 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 1777 } else if (numberOfContours == -1) { 1779 1778 // Compound shapes. 1780 1779 int more = 1; … … 1786 1785 int comp_num_verts = 0, i; 1787 1786 stbtt_vertex *comp_verts = 0, *tmp = 0; 1788 float mtx[6] = { 1,0,0,1,0,0}, m, n;1789 1790 flags = ttSHORT(comp); comp +=2;1791 gidx = ttSHORT(comp); comp +=2;1787 float mtx[6] = {1,0,0,1,0,0}, m, n; 1788 1789 flags = ttSHORT(comp); comp+=2; 1790 gidx = ttSHORT(comp); comp+=2; 1792 1791 1793 1792 if (flags & 2) { // XY values 1794 1793 if (flags & 1) { // shorts 1795 mtx[4] = ttSHORT(comp); comp += 2; 1796 mtx[5] = ttSHORT(comp); comp += 2; 1797 } 1798 else { 1799 mtx[4] = ttCHAR(comp); comp += 1; 1800 mtx[5] = ttCHAR(comp); comp += 1; 1794 mtx[4] = ttSHORT(comp); comp+=2; 1795 mtx[5] = ttSHORT(comp); comp+=2; 1796 } else { 1797 mtx[4] = ttCHAR(comp); comp+=1; 1798 mtx[5] = ttCHAR(comp); comp+=1; 1801 1799 } 1802 1800 } … … 1805 1803 STBTT_assert(0); 1806 1804 } 1807 if (flags & (1 <<3)) { // WE_HAVE_A_SCALE1808 mtx[0] = mtx[3] = ttSHORT(comp) / 16384.0f; comp +=2;1805 if (flags & (1<<3)) { // WE_HAVE_A_SCALE 1806 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 1809 1807 mtx[1] = mtx[2] = 0; 1808 } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE 1809 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; 1810 mtx[1] = mtx[2] = 0; 1811 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 1812 } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO 1813 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; 1814 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; 1815 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; 1816 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 1810 1817 } 1811 else if (flags & (1 << 6)) { // WE_HAVE_AN_X_AND_YSCALE 1812 mtx[0] = ttSHORT(comp) / 16384.0f; comp += 2; 1813 mtx[1] = mtx[2] = 0; 1814 mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2; 1815 } 1816 else if (flags & (1 << 7)) { // WE_HAVE_A_TWO_BY_TWO 1817 mtx[0] = ttSHORT(comp) / 16384.0f; comp += 2; 1818 mtx[1] = ttSHORT(comp) / 16384.0f; comp += 2; 1819 mtx[2] = ttSHORT(comp) / 16384.0f; comp += 2; 1820 mtx[3] = ttSHORT(comp) / 16384.0f; comp += 2; 1821 } 1822 1818 1823 1819 // Find transformation scales. 1824 m = (float) STBTT_sqrt(mtx[0] * mtx[0] + mtx[1] *mtx[1]);1825 n = (float) STBTT_sqrt(mtx[2] * mtx[2] + mtx[3] *mtx[3]);1820 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); 1821 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); 1826 1822 1827 1823 // Get indexed glyph. … … 1831 1827 for (i = 0; i < comp_num_verts; ++i) { 1832 1828 stbtt_vertex* v = &comp_verts[i]; 1833 stbtt_vertex_type x, 1834 x = v->x; y =v->y;1835 v->x = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] *y + mtx[4]));1836 v->y = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] *y + mtx[5]));1837 x = v->cx; y =v->cy;1838 v->cx = (stbtt_vertex_type)(m * (mtx[0] * x + mtx[2] *y + mtx[4]));1839 v->cy = (stbtt_vertex_type)(n * (mtx[1] * x + mtx[3] *y + mtx[5]));1829 stbtt_vertex_type x,y; 1830 x=v->x; y=v->y; 1831 v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 1832 v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 1833 x=v->cx; y=v->cy; 1834 v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 1835 v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 1840 1836 } 1841 1837 // Append vertices. 1842 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices + comp_num_verts) *sizeof(stbtt_vertex), info->userdata);1838 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); 1843 1839 if (!tmp) { 1844 1840 if (vertices) STBTT_free(vertices, info->userdata); … … 1846 1842 return 0; 1847 1843 } 1848 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices * sizeof(stbtt_vertex));1849 STBTT_memcpy(tmp + num_vertices, comp_verts, comp_num_verts *sizeof(stbtt_vertex));1844 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595 1845 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); 1850 1846 if (vertices) STBTT_free(vertices, info->userdata); 1851 1847 vertices = tmp; … … 1854 1850 } 1855 1851 // More components ? 1856 more = flags & (1 << 5); 1857 } 1858 } 1859 else if (numberOfContours < 0) { 1852 more = flags & (1<<5); 1853 } 1854 } else if (numberOfContours < 0) { 1860 1855 // @TODO other compound variations? 1861 1856 STBTT_assert(0); 1862 } 1863 else { 1857 } else { 1864 1858 // numberOfCounters == 0, do nothing 1865 1859 } … … 1900 1894 stbtt__track_vertex(c, cx1, cy1); 1901 1895 } 1902 } 1903 else { 1896 } else { 1904 1897 stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); 1905 c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;1906 c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;1898 c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; 1899 c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; 1907 1900 } 1908 1901 c->num_vertices++; … … 1966 1959 stbtt__buf_skip(&fdselect, glyph_index); 1967 1960 fdselector = stbtt__buf_get8(&fdselect); 1968 } 1969 else if (fmt == 3) { 1961 } else if (fmt == 3) { 1970 1962 nranges = stbtt__buf_get16(&fdselect); 1971 1963 start = stbtt__buf_get16(&fdselect); … … 2001 1993 b0 = stbtt__buf_get8(&b); 2002 1994 switch (b0) { 2003 1995 // @TODO implement hinting 2004 1996 case 0x13: // hintmask 2005 1997 case 0x14: // cntrmask … … 2020 2012 in_header = 0; 2021 2013 if (sp < 2) return STBTT__CSERR("rmoveto stack"); 2022 stbtt__csctx_rmove_to(c, s[sp - 2], s[sp -1]);2014 stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); 2023 2015 break; 2024 2016 case 0x04: // vmoveto 2025 2017 in_header = 0; 2026 2018 if (sp < 1) return STBTT__CSERR("vmoveto stack"); 2027 stbtt__csctx_rmove_to(c, 0, s[sp -1]);2019 stbtt__csctx_rmove_to(c, 0, s[sp-1]); 2028 2020 break; 2029 2021 case 0x16: // hmoveto 2030 2022 in_header = 0; 2031 2023 if (sp < 1) return STBTT__CSERR("hmoveto stack"); 2032 stbtt__csctx_rmove_to(c, s[sp -1], 0);2024 stbtt__csctx_rmove_to(c, s[sp-1], 0); 2033 2025 break; 2034 2026 … … 2036 2028 if (sp < 2) return STBTT__CSERR("rlineto stack"); 2037 2029 for (; i + 1 < sp; i += 2) 2038 stbtt__csctx_rline_to(c, s[i], s[i +1]);2030 stbtt__csctx_rline_to(c, s[i], s[i+1]); 2039 2031 break; 2040 2032 2041 2042 2033 // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical 2034 // starting from a different place. 2043 2035 2044 2036 case 0x07: // vlineto … … 2051 2043 stbtt__csctx_rline_to(c, s[i], 0); 2052 2044 i++; 2053 2045 vlineto: 2054 2046 if (i >= sp) break; 2055 2047 stbtt__csctx_rline_to(c, 0, s[i]); … … 2065 2057 for (;;) { 2066 2058 if (i + 3 >= sp) break; 2067 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);2059 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); 2068 2060 i += 4; 2069 2061 hvcurveto: 2070 2062 if (i + 3 >= sp) break; 2071 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]);2063 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]); 2072 2064 i += 4; 2073 2065 } … … 2077 2069 if (sp < 6) return STBTT__CSERR("rcurveline stack"); 2078 2070 for (; i + 5 < sp; i += 6) 2079 stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i +5]);2071 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); 2080 2072 break; 2081 2073 … … 2083 2075 if (sp < 8) return STBTT__CSERR("rcurveline stack"); 2084 2076 for (; i + 5 < sp - 2; i += 6) 2085 stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i +5]);2077 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); 2086 2078 if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); 2087 stbtt__csctx_rline_to(c, s[i], s[i +1]);2079 stbtt__csctx_rline_to(c, s[i], s[i+1]); 2088 2080 break; 2089 2081 … … 2091 2083 if (sp < 8) return STBTT__CSERR("rlinecurve stack"); 2092 2084 for (; i + 1 < sp - 6; i += 2) 2093 stbtt__csctx_rline_to(c, s[i], s[i +1]);2085 stbtt__csctx_rline_to(c, s[i], s[i+1]); 2094 2086 if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); 2095 stbtt__csctx_rccurve_to(c, s[i], s[i + 1], s[i + 2], s[i + 3], s[i + 4], s[i +5]);2087 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); 2096 2088 break; 2097 2089 … … 2103 2095 for (; i + 3 < sp; i += 4) { 2104 2096 if (b0 == 0x1B) 2105 stbtt__csctx_rccurve_to(c, s[i], f, s[i + 1], s[i + 2], s[i +3], 0.0);2097 stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); 2106 2098 else 2107 stbtt__csctx_rccurve_to(c, f, s[i], s[i + 1], s[i + 2], 0.0, s[i +3]);2099 stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); 2108 2100 f = 0.0; 2109 2101 } … … 2119 2111 case 0x1D: // callgsubr 2120 2112 if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); 2121 v = (int) s[--sp];2113 v = (int) s[--sp]; 2122 2114 if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); 2123 2115 subr_stack[subr_stack_height++] = b; … … 2143 2135 int b1 = stbtt__buf_get8(&b); 2144 2136 switch (b1) { 2145 2146 2137 // @TODO These "flex" implementations ignore the flex-depth and resolution, 2138 // and always draw beziers. 2147 2139 case 0x22: // hflex 2148 2140 if (sp < 7) return STBTT__CSERR("hflex stack"); … … 2189 2181 dx6 = s[8]; 2190 2182 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); 2191 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1 + dy2 +dy5));2183 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); 2192 2184 break; 2193 2185 … … 2205 2197 dy5 = s[9]; 2206 2198 dx6 = dy6 = s[10]; 2207 dx = dx1 + dx2 + dx3 + dx4 +dx5;2208 dy = dy1 + dy2 + dy3 + dy4 +dy5;2199 dx = dx1+dx2+dx3+dx4+dx5; 2200 dy = dy1+dy2+dy3+dy4+dy5; 2209 2201 if (STBTT_fabs(dx) > STBTT_fabs(dy)) 2210 2202 dy6 = -dy; … … 2221 2213 2222 2214 default: 2223 if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) 2215 if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560 2224 2216 return STBTT__CSERR("reserved operator"); 2225 2217 … … 2227 2219 if (b0 == 255) { 2228 2220 f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; 2229 } 2230 else { 2221 } else { 2231 2222 stbtt__buf_skip(&b, -1); 2232 2223 f = (float)(stbtt_int16)stbtt__cff_int(&b); … … 2250 2241 stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); 2251 2242 if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { 2252 *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices *sizeof(stbtt_vertex), info->userdata);2243 *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); 2253 2244 output_ctx.pvertices = *pvertices; 2254 2245 if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { … … 2282 2273 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) 2283 2274 { 2284 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data +info->hhea + 34);2275 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); 2285 2276 if (glyph_index < numOfLongHorMetrics) { 2286 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * glyph_index); 2287 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4 * glyph_index + 2); 2288 } 2289 else { 2290 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4 * (numOfLongHorMetrics - 1)); 2291 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4 * numOfLongHorMetrics + 2 * (glyph_index - numOfLongHorMetrics)); 2277 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); 2278 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); 2279 } else { 2280 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); 2281 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); 2292 2282 } 2293 2283 } … … 2302 2292 if (!info->kern) 2303 2293 return 0; 2304 if (ttUSHORT(data +2) < 1) // number of tables, need at least 12294 if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 2305 2295 return 0; 2306 if (ttUSHORT(data +8) != 1) // horizontal flag must be set in format2296 if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format 2307 2297 return 0; 2308 2298 2309 2299 l = 0; 2310 r = ttUSHORT(data +10) - 1;2300 r = ttUSHORT(data+10) - 1; 2311 2301 needle = glyph1 << 16 | glyph2; 2312 2302 while (l <= r) { 2313 2303 m = (l + r) >> 1; 2314 straw = ttULONG(data + 18 + (m *6)); // note: unaligned read2304 straw = ttULONG(data+18+(m*6)); // note: unaligned read 2315 2305 if (needle < straw) 2316 2306 r = m - 1; … … 2318 2308 l = m + 1; 2319 2309 else 2320 return ttSHORT(data + 22 + (m *6));2310 return ttSHORT(data+22+(m*6)); 2321 2311 } 2322 2312 return 0; … … 2325 2315 static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) 2326 2316 { 2327 stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);2328 switch(coverageFormat) {2329 case 1: {2330 stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);2331 2332 // Binary search.2333 stbtt_int32 l = 0, r = glyphCount -1, m;2334 int straw, needle =glyph;2335 while (l <= r) {2336 stbtt_uint8 *glyphArray = coverageTable + 4;2337 stbtt_uint16 glyphID;2338 m = (l + r) >> 1;2339 glyphID = ttUSHORT(glyphArray + 2 * m);2340 straw = glyphID;2341 if (needle < straw)2342 r = m - 1;2343 else if (needle > straw)2344 l = m + 1;2345 else {2346 return m;2347 }2348 }2349 } break;2350 2351 case 2: {2352 stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);2353 stbtt_uint8 *rangeArray = coverageTable + 4;2354 2355 // Binary search.2356 stbtt_int32 l = 0, r = rangeCount -1, m;2357 int strawStart, strawEnd, needle =glyph;2358 while (l <= r) {2359 stbtt_uint8 *rangeRecord;2360 m = (l + r) >> 1;2361 rangeRecord = rangeArray + 6 * m;2362 strawStart = ttUSHORT(rangeRecord);2363 strawEnd = ttUSHORT(rangeRecord + 2);2364 if (needle < strawStart)2365 r = m - 1;2366 else if (needle > strawEnd)2367 l = m + 1;2368 else {2369 stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);2370 return startCoverageIndex + glyph - strawStart;2371 }2372 }2373 } break;2374 2375 default: {2376 // There are no other cases.2377 STBTT_assert(0);2378 } break;2379 }2380 2381 return -1;2317 stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); 2318 switch(coverageFormat) { 2319 case 1: { 2320 stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); 2321 2322 // Binary search. 2323 stbtt_int32 l=0, r=glyphCount-1, m; 2324 int straw, needle=glyph; 2325 while (l <= r) { 2326 stbtt_uint8 *glyphArray = coverageTable + 4; 2327 stbtt_uint16 glyphID; 2328 m = (l + r) >> 1; 2329 glyphID = ttUSHORT(glyphArray + 2 * m); 2330 straw = glyphID; 2331 if (needle < straw) 2332 r = m - 1; 2333 else if (needle > straw) 2334 l = m + 1; 2335 else { 2336 return m; 2337 } 2338 } 2339 } break; 2340 2341 case 2: { 2342 stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); 2343 stbtt_uint8 *rangeArray = coverageTable + 4; 2344 2345 // Binary search. 2346 stbtt_int32 l=0, r=rangeCount-1, m; 2347 int strawStart, strawEnd, needle=glyph; 2348 while (l <= r) { 2349 stbtt_uint8 *rangeRecord; 2350 m = (l + r) >> 1; 2351 rangeRecord = rangeArray + 6 * m; 2352 strawStart = ttUSHORT(rangeRecord); 2353 strawEnd = ttUSHORT(rangeRecord + 2); 2354 if (needle < strawStart) 2355 r = m - 1; 2356 else if (needle > strawEnd) 2357 l = m + 1; 2358 else { 2359 stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); 2360 return startCoverageIndex + glyph - strawStart; 2361 } 2362 } 2363 } break; 2364 2365 default: { 2366 // There are no other cases. 2367 STBTT_assert(0); 2368 } break; 2369 } 2370 2371 return -1; 2382 2372 } 2383 2373 2384 2374 static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) 2385 2375 { 2386 stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); 2387 switch (classDefFormat) 2388 { 2389 case 1: { 2390 stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); 2391 stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); 2392 stbtt_uint8 *classDef1ValueArray = classDefTable + 6; 2393 2394 if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) 2395 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); 2396 2397 classDefTable = classDef1ValueArray + 2 * glyphCount; 2398 } break; 2399 2400 case 2: { 2401 stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); 2402 stbtt_uint8 *classRangeRecords = classDefTable + 4; 2403 2404 // Binary search. 2405 stbtt_int32 l = 0, r = classRangeCount - 1, m; 2406 int strawStart, strawEnd, needle = glyph; 2407 while (l <= r) { 2408 stbtt_uint8 *classRangeRecord; 2409 m = (l + r) >> 1; 2410 classRangeRecord = classRangeRecords + 6 * m; 2411 strawStart = ttUSHORT(classRangeRecord); 2412 strawEnd = ttUSHORT(classRangeRecord + 2); 2413 if (needle < strawStart) 2414 r = m - 1; 2415 else if (needle > strawEnd) 2416 l = m + 1; 2417 else 2418 return (stbtt_int32)ttUSHORT(classRangeRecord + 4); 2419 } 2420 2421 classDefTable = classRangeRecords + 6 * classRangeCount; 2422 } break; 2423 2424 default: { 2425 // There are no other cases. 2426 STBTT_assert(0); 2427 } break; 2428 } 2429 2430 return -1; 2376 stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); 2377 switch(classDefFormat) 2378 { 2379 case 1: { 2380 stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); 2381 stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); 2382 stbtt_uint8 *classDef1ValueArray = classDefTable + 6; 2383 2384 if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) 2385 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); 2386 2387 // [DEAR IMGUI] Commented to fix static analyzer warning 2388 //classDefTable = classDef1ValueArray + 2 * glyphCount; 2389 } break; 2390 2391 case 2: { 2392 stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); 2393 stbtt_uint8 *classRangeRecords = classDefTable + 4; 2394 2395 // Binary search. 2396 stbtt_int32 l=0, r=classRangeCount-1, m; 2397 int strawStart, strawEnd, needle=glyph; 2398 while (l <= r) { 2399 stbtt_uint8 *classRangeRecord; 2400 m = (l + r) >> 1; 2401 classRangeRecord = classRangeRecords + 6 * m; 2402 strawStart = ttUSHORT(classRangeRecord); 2403 strawEnd = ttUSHORT(classRangeRecord + 2); 2404 if (needle < strawStart) 2405 r = m - 1; 2406 else if (needle > strawEnd) 2407 l = m + 1; 2408 else 2409 return (stbtt_int32)ttUSHORT(classRangeRecord + 4); 2410 } 2411 2412 // [DEAR IMGUI] Commented to fix static analyzer warning 2413 //classDefTable = classRangeRecords + 6 * classRangeCount; 2414 } break; 2415 2416 default: { 2417 // There are no other cases. 2418 STBTT_assert(0); 2419 } break; 2420 } 2421 2422 return -1; 2431 2423 } 2432 2424 … … 2436 2428 static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) 2437 2429 { 2438 stbtt_uint16 lookupListOffset;2439 stbtt_uint8 *lookupList;2440 stbtt_uint16 lookupCount;2441 stbtt_uint8 *data;2442 stbtt_int32 i;2443 2444 if (!info->gpos) return 0;2445 2446 data = info->data + info->gpos;2447 2448 if (ttUSHORT(data +0) != 1) return 0; // Major version 12449 if (ttUSHORT(data +2) != 0) return 0; // Minor version 02450 2451 lookupListOffset = ttUSHORT(data +8);2452 lookupList = data + lookupListOffset;2453 lookupCount = ttUSHORT(lookupList);2454 2455 for (i =0; i<lookupCount; ++i) {2456 stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);2457 stbtt_uint8 *lookupTable = lookupList + lookupOffset;2458 2459 stbtt_uint16 lookupType = ttUSHORT(lookupTable);2460 stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);2461 stbtt_uint8 *subTableOffsets = lookupTable + 6;2462 switch(lookupType) {2463 case 2: { // Pair Adjustment Positioning Subtable2464 stbtt_int32 sti;2465 for (sti =0; sti<subTableCount; sti++) {2466 stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);2467 stbtt_uint8 *table = lookupTable + subtableOffset;2468 stbtt_uint16 posFormat = ttUSHORT(table);2469 stbtt_uint16 coverageOffset = ttUSHORT(table + 2);2470 stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);2471 if (coverageIndex == -1) continue;2472 2473 switch (posFormat) {2474 case 1: {2475 stbtt_int32 l, r, m;2476 int straw, needle;2477 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);2478 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);2479 stbtt_int32 valueRecordPairSizeInBytes = 2;2480 stbtt_uint16 pairSetCount = ttUSHORT(table + 8);2481 stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);2482 stbtt_uint8 *pairValueTable = table + pairPosOffset;2483 stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);2484 stbtt_uint8 *pairValueArray = pairValueTable + 2;2485 // TODO: Support more formats.2486 STBTT_GPOS_TODO_assert(valueFormat1 == 4);2487 if (valueFormat1 != 4) return 0;2488 STBTT_GPOS_TODO_assert(valueFormat2 == 0);2489 if (valueFormat2 != 0) return 0;2490 2491 STBTT_assert(coverageIndex < pairSetCount);2492 STBTT__NOTUSED(pairSetCount);2493 2494 needle =glyph2;2495 r = pairValueCount -1;2496 l =0;2497 2498 // Binary search.2499 while (l <= r) {2500 stbtt_uint16 secondGlyph;2501 stbtt_uint8 *pairValue;2502 m = (l + r) >> 1;2503 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;2504 secondGlyph = ttUSHORT(pairValue);2505 straw = secondGlyph;2506 if (needle < straw)2507 r = m - 1;2508 else if (needle > straw)2509 l = m + 1;2510 else {2511 stbtt_int16 xAdvance = ttSHORT(pairValue + 2);2512 return xAdvance;2513 }2514 }2515 } break;2516 2517 case 2: {2518 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);2519 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);2520 2521 stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);2522 stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);2523 int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);2524 int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);2525 2526 stbtt_uint16 class1Count = ttUSHORT(table + 12);2527 stbtt_uint16 class2Count = ttUSHORT(table + 14);2528 STBTT_assert(glyph1class < class1Count);2529 STBTT_assert(glyph2class < class2Count);2530 2531 // TODO: Support more formats.2532 STBTT_GPOS_TODO_assert(valueFormat1 == 4);2533 if (valueFormat1 != 4) return 0;2534 STBTT_GPOS_TODO_assert(valueFormat2 == 0);2535 if (valueFormat2 != 0) return 0;2536 2537 if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {2538 stbtt_uint8 *class1Records = table + 16;2539 stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);2540 stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);2541 return xAdvance;2542 }2543 } break;2544 2545 default: {2546 // There are no other cases.2547 STBTT_assert(0);2548 break;2549 };2550 }2551 }2552 break;2553 };2554 2555 default:2556 // TODO: Implement other stuff.2557 break;2558 }2559 }2560 2561 return 0;2430 stbtt_uint16 lookupListOffset; 2431 stbtt_uint8 *lookupList; 2432 stbtt_uint16 lookupCount; 2433 stbtt_uint8 *data; 2434 stbtt_int32 i; 2435 2436 if (!info->gpos) return 0; 2437 2438 data = info->data + info->gpos; 2439 2440 if (ttUSHORT(data+0) != 1) return 0; // Major version 1 2441 if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 2442 2443 lookupListOffset = ttUSHORT(data+8); 2444 lookupList = data + lookupListOffset; 2445 lookupCount = ttUSHORT(lookupList); 2446 2447 for (i=0; i<lookupCount; ++i) { 2448 stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i); 2449 stbtt_uint8 *lookupTable = lookupList + lookupOffset; 2450 2451 stbtt_uint16 lookupType = ttUSHORT(lookupTable); 2452 stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4); 2453 stbtt_uint8 *subTableOffsets = lookupTable + 6; 2454 switch(lookupType) { 2455 case 2: { // Pair Adjustment Positioning Subtable 2456 stbtt_int32 sti; 2457 for (sti=0; sti<subTableCount; sti++) { 2458 stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti); 2459 stbtt_uint8 *table = lookupTable + subtableOffset; 2460 stbtt_uint16 posFormat = ttUSHORT(table); 2461 stbtt_uint16 coverageOffset = ttUSHORT(table + 2); 2462 stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1); 2463 if (coverageIndex == -1) continue; 2464 2465 switch (posFormat) { 2466 case 1: { 2467 stbtt_int32 l, r, m; 2468 int straw, needle; 2469 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); 2470 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); 2471 stbtt_int32 valueRecordPairSizeInBytes = 2; 2472 stbtt_uint16 pairSetCount = ttUSHORT(table + 8); 2473 stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex); 2474 stbtt_uint8 *pairValueTable = table + pairPosOffset; 2475 stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable); 2476 stbtt_uint8 *pairValueArray = pairValueTable + 2; 2477 // TODO: Support more formats. 2478 STBTT_GPOS_TODO_assert(valueFormat1 == 4); 2479 if (valueFormat1 != 4) return 0; 2480 STBTT_GPOS_TODO_assert(valueFormat2 == 0); 2481 if (valueFormat2 != 0) return 0; 2482 2483 STBTT_assert(coverageIndex < pairSetCount); 2484 STBTT__NOTUSED(pairSetCount); 2485 2486 needle=glyph2; 2487 r=pairValueCount-1; 2488 l=0; 2489 2490 // Binary search. 2491 while (l <= r) { 2492 stbtt_uint16 secondGlyph; 2493 stbtt_uint8 *pairValue; 2494 m = (l + r) >> 1; 2495 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; 2496 secondGlyph = ttUSHORT(pairValue); 2497 straw = secondGlyph; 2498 if (needle < straw) 2499 r = m - 1; 2500 else if (needle > straw) 2501 l = m + 1; 2502 else { 2503 stbtt_int16 xAdvance = ttSHORT(pairValue + 2); 2504 return xAdvance; 2505 } 2506 } 2507 } break; 2508 2509 case 2: { 2510 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); 2511 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); 2512 2513 stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); 2514 stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); 2515 int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); 2516 int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); 2517 2518 stbtt_uint16 class1Count = ttUSHORT(table + 12); 2519 stbtt_uint16 class2Count = ttUSHORT(table + 14); 2520 STBTT_assert(glyph1class < class1Count); 2521 STBTT_assert(glyph2class < class2Count); 2522 2523 // TODO: Support more formats. 2524 STBTT_GPOS_TODO_assert(valueFormat1 == 4); 2525 if (valueFormat1 != 4) return 0; 2526 STBTT_GPOS_TODO_assert(valueFormat2 == 0); 2527 if (valueFormat2 != 0) return 0; 2528 2529 if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { 2530 stbtt_uint8 *class1Records = table + 16; 2531 stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); 2532 stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); 2533 return xAdvance; 2534 } 2535 } break; 2536 2537 default: { 2538 // There are no other cases. 2539 STBTT_assert(0); 2540 break; 2541 } // [DEAR IMGUI] removed ; 2542 } 2543 } 2544 break; 2545 } // [DEAR IMGUI] removed ; 2546 2547 default: 2548 // TODO: Implement other stuff. 2549 break; 2550 } 2551 } 2552 2553 return 0; 2562 2554 } 2563 2555 … … 2579 2571 if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs 2580 2572 return 0; 2581 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info, ch1), stbtt_FindGlyphIndex(info,ch2));2573 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); 2582 2574 } 2583 2575 2584 2576 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) 2585 2577 { 2586 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info, 2578 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); 2587 2579 } 2588 2580 2589 2581 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) 2590 2582 { 2591 if (ascent ) *ascent = ttSHORT(info->data +info->hhea + 4);2592 if (descent) *descent = ttSHORT(info->data +info->hhea + 6);2593 if (lineGap) *lineGap = ttSHORT(info->data +info->hhea + 8);2583 if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); 2584 if (descent) *descent = ttSHORT(info->data+info->hhea + 6); 2585 if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); 2594 2586 } 2595 2587 … … 2599 2591 if (!tab) 2600 2592 return 0; 2601 if (typoAscent ) *typoAscent = ttSHORT(info->data +tab + 68);2602 if (typoDescent) *typoDescent = ttSHORT(info->data +tab + 70);2603 if (typoLineGap) *typoLineGap = ttSHORT(info->data +tab + 72);2593 if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); 2594 if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); 2595 if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); 2604 2596 return 1; 2605 2597 } … … 2616 2608 { 2617 2609 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); 2618 return (float) height / fheight;2610 return (float) height / fheight; 2619 2611 } 2620 2612 … … 2635 2627 // 2636 2628 2637 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, 2638 { 2639 int x0 = 0, y0 = 0, x1,y1; // =0 suppresses compiler warning2640 if (!stbtt_GetGlyphBox(font, glyph, &x0, &y0, &x1,&y1)) {2629 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) 2630 { 2631 int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning 2632 if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { 2641 2633 // e.g. space character 2642 2634 if (ix0) *ix0 = 0; … … 2644 2636 if (ix1) *ix1 = 0; 2645 2637 if (iy1) *iy1 = 0; 2646 } 2647 else { 2638 } else { 2648 2639 // move to integral bboxes (treating pixels as little squares, what pixels get touched)? 2649 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);2640 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); 2650 2641 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); 2651 if (ix1) *ix1 = STBTT_iceil (x1 * scale_x + shift_x);2652 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);2642 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); 2643 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); 2653 2644 } 2654 2645 } … … 2656 2647 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) 2657 2648 { 2658 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y, 0.0f,0.0f, ix0, iy0, ix1, iy1);2649 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); 2659 2650 } 2660 2651 2661 2652 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) 2662 2653 { 2663 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font, codepoint), scale_x, scale_y, shift_x, shift_y, ix0, iy0, ix1,iy1);2654 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); 2664 2655 } 2665 2656 2666 2657 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) 2667 2658 { 2668 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y, 0.0f, 0.0f, ix0, iy0, ix1,iy1);2659 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); 2669 2660 } 2670 2661 … … 2689 2680 if (hh->first_free) { 2690 2681 void *p = hh->first_free; 2691 hh->first_free = * (void **)p;2682 hh->first_free = * (void **) p; 2692 2683 return p; 2693 } 2694 else { 2684 } else { 2695 2685 if (hh->num_remaining_in_head_chunk == 0) { 2696 2686 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); 2697 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);2687 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); 2698 2688 if (c == NULL) 2699 2689 return NULL; … … 2703 2693 } 2704 2694 --hh->num_remaining_in_head_chunk; 2705 return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;2695 return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; 2706 2696 } 2707 2697 } … … 2709 2699 static void stbtt__hheap_free(stbtt__hheap *hh, void *p) 2710 2700 { 2711 *(void **) p = hh->first_free;2701 *(void **) p = hh->first_free; 2712 2702 hh->first_free = p; 2713 2703 } … … 2724 2714 2725 2715 typedef struct stbtt__edge { 2726 float x0, y0, x1,y1;2716 float x0,y0, x1,y1; 2727 2717 int invert; 2728 2718 } stbtt__edge; … … 2732 2722 { 2733 2723 struct stbtt__active_edge *next; 2734 #if STBTT_RASTERIZER_VERSION==12735 int x, 2724 #if STBTT_RASTERIZER_VERSION==1 2725 int x,dx; 2736 2726 float ey; 2737 2727 int direction; 2738 #elif STBTT_RASTERIZER_VERSION==22739 float fx, fdx,fdy;2728 #elif STBTT_RASTERIZER_VERSION==2 2729 float fx,fdx,fdy; 2740 2730 float direction; 2741 2731 float sy; 2742 2732 float ey; 2743 #else2744 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"2745 #endif2733 #else 2734 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 2735 #endif 2746 2736 } stbtt__active_edge; 2747 2737 … … 2753 2743 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) 2754 2744 { 2755 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);2745 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); 2756 2746 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 2757 2747 STBTT_assert(z != NULL); 2758 2748 if (!z) return z; 2759 2749 2760 2750 // round dx down to avoid overshooting 2761 2751 if (dxdy < 0) … … 2775 2765 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) 2776 2766 { 2777 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);2767 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); 2778 2768 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 2779 2769 STBTT_assert(z != NULL); … … 2781 2771 if (!z) return z; 2782 2772 z->fdx = dxdy; 2783 z->fdy = dxdy != 0.0f ? (1.0f /dxdy) : 0.0f;2773 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; 2784 2774 z->fx = e->x0 + dxdy * (start_point - e->y0); 2785 2775 z->fx -= off_x; … … 2801 2791 { 2802 2792 // non-zero winding fill 2803 int x0 = 0, w =0;2793 int x0=0, w=0; 2804 2794 2805 2795 while (e) { … … 2807 2797 // if we're currently at zero, we need to record the edge start point 2808 2798 x0 = e->x; w += e->direction; 2809 } 2810 else { 2799 } else { 2811 2800 int x1 = e->x; w += e->direction; 2812 2801 // if we went to zero, we need to draw … … 2818 2807 if (i == j) { 2819 2808 // x0,x1 are the same pixel, so compute combined coverage 2820 scanline[i] = scanline[i] + (stbtt_uint8)((x1 - x0) * max_weight >> STBTT_FIXSHIFT); 2821 } 2822 else { 2809 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); 2810 } else { 2823 2811 if (i >= 0) // add antialiasing for x0 2824 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);2812 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); 2825 2813 else 2826 2814 i = -1; // clip 2827 2815 2828 2816 if (j < len) // add antialiasing for x1 2829 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);2817 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); 2830 2818 else 2831 2819 j = len; // clip 2832 2820 2833 2821 for (++i; i < j; ++i) // fill pixels between x0 and x1 2834 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;2822 scanline[i] = scanline[i] + (stbtt_uint8) max_weight; 2835 2823 } 2836 2824 } 2837 2825 } 2838 2826 } 2839 2827 2840 2828 e = e->next; 2841 2829 } … … 2846 2834 stbtt__hheap hh = { 0, 0, 0 }; 2847 2835 stbtt__active_edge *active = NULL; 2848 int y, j =0;2836 int y,j=0; 2849 2837 int max_weight = (255 / vsubsample); // weight per vertical scanline 2850 2838 int s; // vertical subsample index … … 2852 2840 2853 2841 if (result->w > 512) 2854 scanline = (unsigned char *) STBTT_malloc(result->w, userdata);2842 scanline = (unsigned char *) STBTT_malloc(result->w, userdata); 2855 2843 else 2856 2844 scanline = scanline_data; 2857 2845 2858 2846 y = off_y * vsubsample; 2859 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;2847 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; 2860 2848 2861 2849 while (j < result->h) { 2862 2850 STBTT_memset(scanline, 0, result->w); 2863 for (s =0; s < vsubsample; ++s) {2851 for (s=0; s < vsubsample; ++s) { 2864 2852 // find center of pixel for this scanline 2865 2853 float scan_y = y + 0.5f; … … 2875 2863 z->direction = 0; 2876 2864 stbtt__hheap_free(&hh, z); 2877 } 2878 else { 2865 } else { 2879 2866 z->x += z->dx; // advance to position for current scanline 2880 2867 step = &((*step)->next); // advance through list … … 2883 2870 2884 2871 // resort the list if needed 2885 for 2886 int changed =0;2872 for(;;) { 2873 int changed=0; 2887 2874 step = &active; 2888 2875 while (*step && (*step)->next) { … … 2913 2900 z->next = active; 2914 2901 active = z; 2915 } 2916 else { 2902 } else { 2917 2903 // find thing to insert AFTER 2918 2904 stbtt__active_edge *p = active; … … 2956 2942 if (y1 < e->sy) return; 2957 2943 if (y0 < e->sy) { 2958 x0 += (x1 - x0) * (e->sy - y0) / (y1 -y0);2944 x0 += (x1-x0) * (e->sy - y0) / (y1-y0); 2959 2945 y0 = e->sy; 2960 2946 } 2961 2947 if (y1 > e->ey) { 2962 x1 += (x1 - x0) * (e->ey - y1) / (y1 -y0);2948 x1 += (x1-x0) * (e->ey - y1) / (y1-y0); 2963 2949 y1 = e->ey; 2964 2950 } 2965 2951 2966 2952 if (x0 == x) 2967 STBTT_assert(x1 <= x +1);2968 else if (x0 == x +1)2953 STBTT_assert(x1 <= x+1); 2954 else if (x0 == x+1) 2969 2955 STBTT_assert(x1 >= x); 2970 2956 else if (x0 <= x) 2971 2957 STBTT_assert(x1 <= x); 2972 else if (x0 >= x +1)2973 STBTT_assert(x1 >= x +1);2958 else if (x0 >= x+1) 2959 STBTT_assert(x1 >= x+1); 2974 2960 else 2975 STBTT_assert(x1 >= x && x1 <= x +1);2961 STBTT_assert(x1 >= x && x1 <= x+1); 2976 2962 2977 2963 if (x0 <= x && x1 <= x) 2978 scanline[x] += e->direction * (y1 -y0);2979 else if (x0 >= x + 1 && x1 >= x +1)2964 scanline[x] += e->direction * (y1-y0); 2965 else if (x0 >= x+1 && x1 >= x+1) 2980 2966 ; 2981 2967 else { 2982 STBTT_assert(x0 >= x && x0 <= x + 1 && x1 >= x && x1 <= x +1);2983 scanline[x] += e->direction * (y1 - y0) * (1 - ((x0 - x) + (x1 - x)) /2); // coverage = 1 - average x position2968 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); 2969 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position 2984 2970 } 2985 2971 } … … 2987 2973 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) 2988 2974 { 2989 float y_bottom = y_top +1;2975 float y_bottom = y_top+1; 2990 2976 2991 2977 while (e) { … … 2999 2985 if (x0 < len) { 3000 2986 if (x0 >= 0) { 3001 stbtt__handle_clipped_edge(scanline, (int)x0, e, x0, y_top, x0, y_bottom); 3002 stbtt__handle_clipped_edge(scanline_fill - 1, (int)x0 + 1, e, x0, y_top, x0, y_bottom); 3003 } 3004 else { 3005 stbtt__handle_clipped_edge(scanline_fill - 1, 0, e, x0, y_top, x0, y_bottom); 2987 stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); 2988 stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); 2989 } else { 2990 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); 3006 2991 } 3007 2992 } 3008 } 3009 else { 2993 } else { 3010 2994 float x0 = e->fx; 3011 2995 float dx = e->fdx; 3012 2996 float xb = x0 + dx; 3013 2997 float x_top, x_bottom; 3014 float sy0, 2998 float sy0,sy1; 3015 2999 float dy = e->fdy; 3016 3000 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); … … 3022 3006 x_top = x0 + dx * (e->sy - y_top); 3023 3007 sy0 = e->sy; 3024 } 3025 else { 3008 } else { 3026 3009 x_top = x0; 3027 3010 sy0 = y_top; … … 3030 3013 x_bottom = x0 + dx * (e->ey - y_top); 3031 3014 sy1 = e->ey; 3032 } 3033 else { 3015 } else { 3034 3016 x_bottom = xb; 3035 3017 sy1 = y_bottom; … … 3039 3021 // from here on, we don't have to range check x values 3040 3022 3041 if ((int) x_top == (int)x_bottom) {3023 if ((int) x_top == (int) x_bottom) { 3042 3024 float height; 3043 3025 // simple case, only spans one pixel 3044 int x = (int) x_top;3026 int x = (int) x_top; 3045 3027 height = sy1 - sy0; 3046 3028 STBTT_assert(x >= 0 && x < len); 3047 scanline[x] += e->direction * (1 - ((x_top - x) + (x_bottom - x)) /2) * height;3029 scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; 3048 3030 scanline_fill[x] += e->direction * height; // everything right of this pixel is filled 3049 } 3050 else { 3051 int x, x1, x2; 3031 } else { 3032 int x,x1,x2; 3052 3033 float y_crossing, step, sign, area; 3053 3034 // covers 2+ pixels … … 3062 3043 dy = -dy; 3063 3044 t = x0, x0 = xb, xb = t; 3045 // [DEAR IMGUI] Fix static analyzer warning 3046 (void)dx; // [ImGui: fix static analyzer warning] 3064 3047 } 3065 3048 3066 x1 = (int) x_top;3067 x2 = (int) x_bottom;3049 x1 = (int) x_top; 3050 x2 = (int) x_bottom; 3068 3051 // compute intersection with y axis at x1+1 3069 y_crossing = (x1 +1 - x0) * dy + y_top;3052 y_crossing = (x1+1 - x0) * dy + y_top; 3070 3053 3071 3054 sign = e->direction; 3072 3055 // area of the rectangle covered from y0..y_crossing 3073 area = sign * (y_crossing -sy0);3056 area = sign * (y_crossing-sy0); 3074 3057 // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) 3075 scanline[x1] += area * (1 - ((x_top - x1) + (x1 + 1 - x1)) /2);3058 scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); 3076 3059 3077 3060 step = sign * dy; 3078 for (x = x1 +1; x < x2; ++x) {3079 scanline[x] += area + step /2;3061 for (x = x1+1; x < x2; ++x) { 3062 scanline[x] += area + step/2; 3080 3063 area += step; 3081 3064 } 3082 y_crossing += dy * (x2 - (x1 +1));3065 y_crossing += dy * (x2 - (x1+1)); 3083 3066 3084 3067 STBTT_assert(STBTT_fabs(area) <= 1.01f); 3085 3068 3086 scanline[x2] += area + sign * (1 - ((x2 - x2) + (x_bottom - x2)) / 2) * (sy1 -y_crossing);3087 3088 scanline_fill[x2] += sign * (sy1 -sy0);3069 scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); 3070 3071 scanline_fill[x2] += sign * (sy1-sy0); 3089 3072 } 3090 } 3091 else { 3073 } else { 3092 3074 // if edge goes outside of box we're drawing, we require 3093 3075 // clipping logic. since this does not match the intended use … … 3095 3077 // force implementation 3096 3078 int x; 3097 for (x =0; x < len; ++x) {3079 for (x=0; x < len; ++x) { 3098 3080 // cases: 3099 3081 // … … 3111 3093 // rename variables to clearly-defined pairs 3112 3094 float y0 = y_top; 3113 float x1 = (float) (x);3114 float x2 = (float) (x +1);3095 float x1 = (float) (x); 3096 float x2 = (float) (x+1); 3115 3097 float x3 = xb; 3116 3098 float y3 = y_bottom; … … 3120 3102 // y = (x - e->x) / e->dx + y_top 3121 3103 float y1 = (x - x0) / dx + y_top; 3122 float y2 = (x +1 - x0) / dx + y_top;3104 float y2 = (x+1 - x0) / dx + y_top; 3123 3105 3124 3106 if (x0 < x1 && x3 > x2) { // three segments descending down-right 3125 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1); 3126 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x2, y2); 3127 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3); 3128 } 3129 else if (x3 < x1 && x0 > x2) { // three segments descending down-left 3130 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2); 3131 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x1, y1); 3132 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3); 3133 } 3134 else if (x0 < x1 && x3 > x1) { // two segments across x, down-right 3135 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1); 3136 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3); 3137 } 3138 else if (x3 < x1 && x0 > x1) { // two segments across x, down-left 3139 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x1, y1); 3140 stbtt__handle_clipped_edge(scanline, x, e, x1, y1, x3, y3); 3141 } 3142 else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right 3143 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2); 3144 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3); 3145 } 3146 else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left 3147 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x2, y2); 3148 stbtt__handle_clipped_edge(scanline, x, e, x2, y2, x3, y3); 3149 } 3150 else { // one segment 3151 stbtt__handle_clipped_edge(scanline, x, e, x0, y0, x3, y3); 3107 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 3108 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); 3109 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 3110 } else if (x3 < x1 && x0 > x2) { // three segments descending down-left 3111 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 3112 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); 3113 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 3114 } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right 3115 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 3116 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 3117 } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left 3118 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 3119 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 3120 } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right 3121 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 3122 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 3123 } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left 3124 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 3125 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 3126 } else { // one segment 3127 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); 3152 3128 } 3153 3129 } … … 3163 3139 stbtt__hheap hh = { 0, 0, 0 }; 3164 3140 stbtt__active_edge *active = NULL; 3165 int y, j =0, i;3141 int y,j=0, i; 3166 3142 float scanline_data[129], *scanline, *scanline2; 3167 3143 … … 3169 3145 3170 3146 if (result->w > 64) 3171 scanline = (float *) STBTT_malloc((result->w * 2 +1) * sizeof(float), userdata);3147 scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); 3172 3148 else 3173 3149 scanline = scanline_data; … … 3176 3152 3177 3153 y = off_y; 3178 e[n].y0 = (float) (off_y + result->h) + 1;3154 e[n].y0 = (float) (off_y + result->h) + 1; 3179 3155 3180 3156 while (j < result->h) { 3181 3157 // find center of pixel for this scanline 3182 float scan_y_top = y + 0.0f;3158 float scan_y_top = y + 0.0f; 3183 3159 float scan_y_bottom = y + 1.0f; 3184 3160 stbtt__active_edge **step = &active; 3185 3161 3186 STBTT_memset(scanline , 0, result->w *sizeof(scanline[0]));3187 STBTT_memset(scanline2, 0, (result->w + 1) *sizeof(scanline[0]));3162 STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); 3163 STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); 3188 3164 3189 3165 // update all active edges; … … 3196 3172 z->direction = 0; 3197 3173 stbtt__hheap_free(&hh, z); 3198 } 3199 else { 3174 } else { 3200 3175 step = &((*step)->next); // advance through list 3201 3176 } … … 3207 3182 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); 3208 3183 if (z != NULL) { 3209 STBTT_assert(z->ey >= scan_y_top); 3184 if (j == 0 && off_y != 0) { 3185 if (z->ey < scan_y_top) { 3186 // this can happen due to subpixel positioning and some kind of fp rounding error i think 3187 z->ey = scan_y_top; 3188 } 3189 } 3190 STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds 3210 3191 // insert at front 3211 3192 z->next = active; … … 3218 3199 // now process all active edges 3219 3200 if (active) 3220 stbtt__fill_active_edges_new(scanline, scanline2 +1, result->w, active, scan_y_top);3201 stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); 3221 3202 3222 3203 { 3223 3204 float sum = 0; 3224 for (i =0; i < result->w; ++i) {3205 for (i=0; i < result->w; ++i) { 3225 3206 float k; 3226 3207 int m; 3227 3208 sum += scanline2[i]; 3228 3209 k = scanline[i] + sum; 3229 k = (float) STBTT_fabs(k) *255 + 0.5f;3230 m = (int) k;3210 k = (float) STBTT_fabs(k)*255 + 0.5f; 3211 m = (int) k; 3231 3212 if (m > 255) m = 255; 3232 result->pixels[j*result->stride + i] = (unsigned char) m;3213 result->pixels[j*result->stride + i] = (unsigned char) m; 3233 3214 } 3234 3215 } … … 3258 3239 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) 3259 3240 { 3260 int i, 3261 for (i =1; i < n; ++i) {3241 int i,j; 3242 for (i=1; i < n; ++i) { 3262 3243 stbtt__edge t = p[i], *a = &t; 3263 3244 j = i; 3264 3245 while (j > 0) { 3265 stbtt__edge *b = &p[j -1];3266 int c = STBTT__COMPARE(a, 3246 stbtt__edge *b = &p[j-1]; 3247 int c = STBTT__COMPARE(a,b); 3267 3248 if (!c) break; 3268 p[j] = p[j -1];3249 p[j] = p[j-1]; 3269 3250 --j; 3270 3251 } … … 3276 3257 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) 3277 3258 { 3278 /* thresh hold for transitioning to insertion sort */3259 /* threshold for transitioning to insertion sort */ 3279 3260 while (n > 12) { 3280 3261 stbtt__edge t; 3281 int c01, c12, c, m, i,j;3262 int c01,c12,c,m,i,j; 3282 3263 3283 3264 /* compute median of three */ 3284 3265 m = n >> 1; 3285 c01 = STBTT__COMPARE(&p[0], 3286 c12 = STBTT__COMPARE(&p[m], &p[n -1]);3266 c01 = STBTT__COMPARE(&p[0],&p[m]); 3267 c12 = STBTT__COMPARE(&p[m],&p[n-1]); 3287 3268 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ 3288 3269 if (c01 != c12) { 3289 3270 /* otherwise, we'll need to swap something else to middle */ 3290 3271 int z; 3291 c = STBTT__COMPARE(&p[0], &p[n -1]);3272 c = STBTT__COMPARE(&p[0],&p[n-1]); 3292 3273 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ 3293 3274 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ 3294 z = (c == c12) ? 0 : n -1;3275 z = (c == c12) ? 0 : n-1; 3295 3276 t = p[z]; 3296 3277 p[z] = p[m]; … … 3304 3285 3305 3286 /* partition loop */ 3306 i =1;3307 j = n -1;3308 for 3287 i=1; 3288 j=n-1; 3289 for(;;) { 3309 3290 /* handling of equality is crucial here */ 3310 3291 /* for sentinels & efficiency with duplicates */ 3311 for (;; 3292 for (;;++i) { 3312 3293 if (!STBTT__COMPARE(&p[i], &p[0])) break; 3313 3294 } 3314 for (;; 3295 for (;;--j) { 3315 3296 if (!STBTT__COMPARE(&p[0], &p[j])) break; 3316 3297 } … … 3325 3306 } 3326 3307 /* recurse on smaller side, iterate on larger */ 3327 if (j < (n - i)) { 3328 stbtt__sort_edges_quicksort(p, j); 3329 p = p + i; 3330 n = n - i; 3331 } 3332 else { 3333 stbtt__sort_edges_quicksort(p + i, n - i); 3308 if (j < (n-i)) { 3309 stbtt__sort_edges_quicksort(p,j); 3310 p = p+i; 3311 n = n-i; 3312 } else { 3313 stbtt__sort_edges_quicksort(p+i, n-i); 3334 3314 n = j; 3335 3315 } … … 3345 3325 typedef struct 3346 3326 { 3347 float x, 3327 float x,y; 3348 3328 } stbtt__point; 3349 3329 … … 3352 3332 float y_scale_inv = invert ? -scale_y : scale_y; 3353 3333 stbtt__edge *e; 3354 int n, i, j, k,m;3334 int n,i,j,k,m; 3355 3335 #if STBTT_RASTERIZER_VERSION == 1 3356 3336 int vsubsample = result->h < 8 ? 15 : 5; … … 3358 3338 int vsubsample = 1; 3359 3339 #else 3360 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"3340 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 3361 3341 #endif 3362 3342 // vsubsample should divide 255 evenly; otherwise we won't reach full opacity … … 3364 3344 // now we have to blow out the windings into explicit edge lists 3365 3345 n = 0; 3366 for (i =0; i < windings; ++i)3346 for (i=0; i < windings; ++i) 3367 3347 n += wcount[i]; 3368 3348 3369 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n +1), userdata); // add an extra one as a sentinel3349 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel 3370 3350 if (e == 0) return; 3371 3351 n = 0; 3372 3352 3373 m =0;3374 for (i =0; i < windings; ++i) {3353 m=0; 3354 for (i=0; i < windings; ++i) { 3375 3355 stbtt__point *p = pts + m; 3376 3356 m += wcount[i]; 3377 j = wcount[i] -1;3378 for (k = 0; k < wcount[i]; j =k++) {3379 int a = k, b =j;3357 j = wcount[i]-1; 3358 for (k=0; k < wcount[i]; j=k++) { 3359 int a=k,b=j; 3380 3360 // skip the edge if horizontal 3381 3361 if (p[j].y == p[k].y) … … 3385 3365 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { 3386 3366 e[n].invert = 1; 3387 a = j, b =k;3367 a=j,b=k; 3388 3368 } 3389 3369 e[n].x0 = p[a].x * scale_x + shift_x; … … 3412 3392 } 3413 3393 3414 // tessel ate until threshhold p is happy... @TODO warped to compensate for non-linear stretching3394 // tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching 3415 3395 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) 3416 3396 { 3417 3397 // midpoint 3418 float mx = (x0 + 2 * x1 + x2) /4;3419 float my = (y0 + 2 * y1 + y2) /4;3398 float mx = (x0 + 2*x1 + x2)/4; 3399 float my = (y0 + 2*y1 + y2)/4; 3420 3400 // versus directly drawn line 3421 float dx = (x0 + x2) /2 - mx;3422 float dy = (y0 + y2) /2 - my;3401 float dx = (x0+x2)/2 - mx; 3402 float dy = (y0+y2)/2 - my; 3423 3403 if (n > 16) // 65536 segments on one curve better be enough! 3424 3404 return 1; 3425 if (dx*dx + dy * dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA 3426 stbtt__tesselate_curve(points, num_points, x0, y0, (x0 + x1) / 2.0f, (y0 + y1) / 2.0f, mx, my, objspace_flatness_squared, n + 1); 3427 stbtt__tesselate_curve(points, num_points, mx, my, (x1 + x2) / 2.0f, (y1 + y2) / 2.0f, x2, y2, objspace_flatness_squared, n + 1); 3428 } 3429 else { 3430 stbtt__add_point(points, *num_points, x2, y2); 3431 *num_points = *num_points + 1; 3405 if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA 3406 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); 3407 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); 3408 } else { 3409 stbtt__add_point(points, *num_points,x2,y2); 3410 *num_points = *num_points+1; 3432 3411 } 3433 3412 return 1; … … 3437 3416 { 3438 3417 // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough 3439 float dx0 = x1 -x0;3440 float dy0 = y1 -y0;3441 float dx1 = x2 -x1;3442 float dy1 = y2 -y1;3443 float dx2 = x3 -x2;3444 float dy2 = y3 -y2;3445 float dx = x3 -x0;3446 float dy = y3 -y0;3447 float longlen = (float) (STBTT_sqrt(dx0*dx0 + dy0 * dy0) + STBTT_sqrt(dx1*dx1 + dy1 * dy1) + STBTT_sqrt(dx2*dx2 + dy2 *dy2));3448 float shortlen = (float) STBTT_sqrt(dx*dx + dy *dy);3449 float flatness_squared = longlen * longlen - shortlen *shortlen;3418 float dx0 = x1-x0; 3419 float dy0 = y1-y0; 3420 float dx1 = x2-x1; 3421 float dy1 = y2-y1; 3422 float dx2 = x3-x2; 3423 float dy2 = y3-y2; 3424 float dx = x3-x0; 3425 float dy = y3-y0; 3426 float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); 3427 float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); 3428 float flatness_squared = longlen*longlen-shortlen*shortlen; 3450 3429 3451 3430 if (n > 16) // 65536 segments on one curve better be enough! … … 3453 3432 3454 3433 if (flatness_squared > objspace_flatness_squared) { 3455 float x01 = (x0 + x1) / 2; 3456 float y01 = (y0 + y1) / 2; 3457 float x12 = (x1 + x2) / 2; 3458 float y12 = (y1 + y2) / 2; 3459 float x23 = (x2 + x3) / 2; 3460 float y23 = (y2 + y3) / 2; 3461 3462 float xa = (x01 + x12) / 2; 3463 float ya = (y01 + y12) / 2; 3464 float xb = (x12 + x23) / 2; 3465 float yb = (y12 + y23) / 2; 3466 3467 float mx = (xa + xb) / 2; 3468 float my = (ya + yb) / 2; 3469 3470 stbtt__tesselate_cubic(points, num_points, x0, y0, x01, y01, xa, ya, mx, my, objspace_flatness_squared, n + 1); 3471 stbtt__tesselate_cubic(points, num_points, mx, my, xb, yb, x23, y23, x3, y3, objspace_flatness_squared, n + 1); 3472 } 3473 else { 3474 stbtt__add_point(points, *num_points, x3, y3); 3475 *num_points = *num_points + 1; 3434 float x01 = (x0+x1)/2; 3435 float y01 = (y0+y1)/2; 3436 float x12 = (x1+x2)/2; 3437 float y12 = (y1+y2)/2; 3438 float x23 = (x2+x3)/2; 3439 float y23 = (y2+y3)/2; 3440 3441 float xa = (x01+x12)/2; 3442 float ya = (y01+y12)/2; 3443 float xb = (x12+x23)/2; 3444 float yb = (y12+y23)/2; 3445 3446 float mx = (xa+xb)/2; 3447 float my = (ya+yb)/2; 3448 3449 stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); 3450 stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); 3451 } else { 3452 stbtt__add_point(points, *num_points,x3,y3); 3453 *num_points = *num_points+1; 3476 3454 } 3477 3455 } … … 3480 3458 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) 3481 3459 { 3482 stbtt__point *points =0;3483 int num_points =0;3460 stbtt__point *points=0; 3461 int num_points=0; 3484 3462 3485 3463 float objspace_flatness_squared = objspace_flatness * objspace_flatness; 3486 int i, n = 0, start =0, pass;3464 int i,n=0,start=0, pass; 3487 3465 3488 3466 // count how many "moves" there are to get the contour count 3489 for (i =0; i < num_verts; ++i)3467 for (i=0; i < num_verts; ++i) 3490 3468 if (vertices[i].type == STBTT_vmove) 3491 3469 ++n; … … 3494 3472 if (n == 0) return 0; 3495 3473 3496 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);3474 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); 3497 3475 3498 3476 if (*contour_lengths == 0) { … … 3502 3480 3503 3481 // make two passes through the points so we don't need to realloc 3504 for (pass =0; pass < 2; ++pass) {3505 float x = 0, y =0;3482 for (pass=0; pass < 2; ++pass) { 3483 float x=0,y=0; 3506 3484 if (pass == 1) { 3507 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);3485 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); 3508 3486 if (points == NULL) goto error; 3509 3487 } 3510 3488 num_points = 0; 3511 n 3512 for (i =0; i < num_verts; ++i) {3489 n= -1; 3490 for (i=0; i < num_verts; ++i) { 3513 3491 switch (vertices[i].type) { 3514 case STBTT_vmove:3515 // start the next contour3516 if (n >= 0)3517 (*contour_lengths)[n] = num_points - start;3518 ++n;3519 start = num_points;3520 3521 x = vertices[i].x, y = vertices[i].y;3522 stbtt__add_point(points, num_points++, x,y);3523 break;3524 case STBTT_vline:3525 x = vertices[i].x, y = vertices[i].y;3526 stbtt__add_point(points, num_points++, x, y);3527 break;3528 case STBTT_vcurve:3529 stbtt__tesselate_curve(points, &num_points, x,y,3530 vertices[i].cx, vertices[i].cy,3531 vertices[i].x,vertices[i].y,3532 objspace_flatness_squared, 0);3533 x = vertices[i].x, y = vertices[i].y;3534 break;3535 case STBTT_vcubic:3536 stbtt__tesselate_cubic(points, &num_points, x,y,3537 vertices[i].cx, vertices[i].cy,3538 vertices[i].cx1, vertices[i].cy1,3539 vertices[i].x,vertices[i].y,3540 objspace_flatness_squared, 0);3541 x = vertices[i].x, y = vertices[i].y;3542 break;3492 case STBTT_vmove: 3493 // start the next contour 3494 if (n >= 0) 3495 (*contour_lengths)[n] = num_points - start; 3496 ++n; 3497 start = num_points; 3498 3499 x = vertices[i].x, y = vertices[i].y; 3500 stbtt__add_point(points, num_points++, x,y); 3501 break; 3502 case STBTT_vline: 3503 x = vertices[i].x, y = vertices[i].y; 3504 stbtt__add_point(points, num_points++, x, y); 3505 break; 3506 case STBTT_vcurve: 3507 stbtt__tesselate_curve(points, &num_points, x,y, 3508 vertices[i].cx, vertices[i].cy, 3509 vertices[i].x, vertices[i].y, 3510 objspace_flatness_squared, 0); 3511 x = vertices[i].x, y = vertices[i].y; 3512 break; 3513 case STBTT_vcubic: 3514 stbtt__tesselate_cubic(points, &num_points, x,y, 3515 vertices[i].cx, vertices[i].cy, 3516 vertices[i].cx1, vertices[i].cy1, 3517 vertices[i].x, vertices[i].y, 3518 objspace_flatness_squared, 0); 3519 x = vertices[i].x, y = vertices[i].y; 3520 break; 3543 3521 } 3544 3522 } … … 3557 3535 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) 3558 3536 { 3559 float scale = scale_x > scale_y ? scale_y : scale_x;3560 int winding_count = 0;3561 int *winding_lengths = NULL;3537 float scale = scale_x > scale_y ? scale_y : scale_x; 3538 int winding_count = 0; 3539 int *winding_lengths = NULL; 3562 3540 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); 3563 3541 if (windings) { … … 3575 3553 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) 3576 3554 { 3577 int ix0, iy0, ix1,iy1;3555 int ix0,iy0,ix1,iy1; 3578 3556 stbtt__bitmap gbm; 3579 stbtt_vertex *vertices; 3557 stbtt_vertex *vertices; 3580 3558 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); 3581 3559 … … 3589 3567 } 3590 3568 3591 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0, &iy0, &ix1,&iy1);3569 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); 3592 3570 3593 3571 // now we get the size … … 3596 3574 gbm.pixels = NULL; // in case we error 3597 3575 3598 if (width ) *width= gbm.w;3576 if (width ) *width = gbm.w; 3599 3577 if (height) *height = gbm.h; 3600 if (xoff ) *xoff= ix0;3601 if (yoff ) *yoff= iy0;3602 3578 if (xoff ) *xoff = ix0; 3579 if (yoff ) *yoff = iy0; 3580 3603 3581 if (gbm.w && gbm.h) { 3604 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);3582 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); 3605 3583 if (gbm.pixels) { 3606 3584 gbm.stride = gbm.w; … … 3611 3589 STBTT_free(vertices, info->userdata); 3612 3590 return gbm.pixels; 3613 } 3591 } 3614 3592 3615 3593 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) … … 3620 3598 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) 3621 3599 { 3622 int ix0, 3600 int ix0,iy0; 3623 3601 stbtt_vertex *vertices; 3624 3602 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); 3625 stbtt__bitmap gbm; 3626 3627 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0, &iy0, 0,0);3603 stbtt__bitmap gbm; 3604 3605 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); 3628 3606 gbm.pixels = output; 3629 3607 gbm.w = out_w; … … 3632 3610 3633 3611 if (gbm.w && gbm.h) 3634 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, 3612 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); 3635 3613 3636 3614 STBTT_free(vertices, info->userdata); … … 3639 3617 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) 3640 3618 { 3641 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f, 3619 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); 3642 3620 } 3643 3621 3644 3622 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) 3645 3623 { 3646 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info, codepoint), width, height, xoff,yoff);3647 } 3624 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); 3625 } 3648 3626 3649 3627 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) 3650 3628 { 3651 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, 3629 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)); 3652 3630 } 3653 3631 3654 3632 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) 3655 3633 { 3656 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info, 3634 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); 3657 3635 } 3658 3636 3659 3637 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) 3660 3638 { 3661 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, codepoint, width, height, xoff,yoff);3662 } 3639 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); 3640 } 3663 3641 3664 3642 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) 3665 3643 { 3666 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f, 3644 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); 3667 3645 } 3668 3646 … … 3674 3652 3675 3653 static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) 3676 float pixel_height, // height of font in pixels3677 unsigned char *pixels, int pw, int ph, // bitmap to be filled in3678 int first_char, int num_chars, // characters to bake3679 stbtt_bakedchar *chardata)3654 float pixel_height, // height of font in pixels 3655 unsigned char *pixels, int pw, int ph, // bitmap to be filled in 3656 int first_char, int num_chars, // characters to bake 3657 stbtt_bakedchar *chardata) 3680 3658 { 3681 3659 float scale; 3682 int x, y,bottom_y, i;3660 int x,y,bottom_y, i; 3683 3661 stbtt_fontinfo f; 3684 3662 f.userdata = NULL; … … 3686 3664 return -1; 3687 3665 STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels 3688 x = y =1;3666 x=y=1; 3689 3667 bottom_y = 1; 3690 3668 3691 3669 scale = stbtt_ScaleForPixelHeight(&f, pixel_height); 3692 3670 3693 for (i =0; i < num_chars; ++i) {3694 int advance, lsb, x0, y0, x1, y1, gw,gh;3671 for (i=0; i < num_chars; ++i) { 3672 int advance, lsb, x0,y0,x1,y1,gw,gh; 3695 3673 int g = stbtt_FindGlyphIndex(&f, first_char + i); 3696 3674 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); 3697 stbtt_GetGlyphBitmapBox(&f, g, scale, scale, &x0, &y0, &x1,&y1);3698 gw = x1 -x0;3699 gh = y1 -y0;3675 stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); 3676 gw = x1-x0; 3677 gh = y1-y0; 3700 3678 if (x + gw + 1 >= pw) 3701 3679 y = bottom_y, x = 1; // advance to next row 3702 3680 if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row 3703 3681 return -i; 3704 STBTT_assert(x +gw < pw);3705 STBTT_assert(y +gh < ph);3706 stbtt_MakeGlyphBitmap(&f, pixels + x + y * pw, gw, gh, pw, scale,scale, g);3707 chardata[i].x0 = (stbtt_int16) x;3708 chardata[i].y0 = (stbtt_int16) y;3709 chardata[i].x1 = (stbtt_int16) (x + gw);3710 chardata[i].y1 = (stbtt_int16) (y + gh);3682 STBTT_assert(x+gw < pw); 3683 STBTT_assert(y+gh < ph); 3684 stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); 3685 chardata[i].x0 = (stbtt_int16) x; 3686 chardata[i].y0 = (stbtt_int16) y; 3687 chardata[i].x1 = (stbtt_int16) (x + gw); 3688 chardata[i].y1 = (stbtt_int16) (y + gh); 3711 3689 chardata[i].xadvance = scale * advance; 3712 chardata[i].xoff = (float)x0;3713 chardata[i].yoff = (float)y0;3690 chardata[i].xoff = (float) x0; 3691 chardata[i].yoff = (float) y0; 3714 3692 x = x + gw + 1; 3715 if (y + gh +1 > bottom_y)3716 bottom_y = y + gh +1;3693 if (y+gh+1 > bottom_y) 3694 bottom_y = y+gh+1; 3717 3695 } 3718 3696 return bottom_y; … … 3762 3740 typedef struct 3763 3741 { 3764 int width, 3765 int x, y,bottom_y;3742 int width,height; 3743 int x,y,bottom_y; 3766 3744 } stbrp_context; 3767 3745 … … 3773 3751 struct stbrp_rect 3774 3752 { 3775 stbrp_coord x, 3776 int id, w, h,was_packed;3753 stbrp_coord x,y; 3754 int id,w,h,was_packed; 3777 3755 }; 3778 3756 3779 3757 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) 3780 3758 { 3781 con->width = pw;3759 con->width = pw; 3782 3760 con->height = ph; 3783 3761 con->x = 0; … … 3785 3763 con->bottom_y = 0; 3786 3764 STBTT__NOTUSED(nodes); 3787 STBTT__NOTUSED(num_nodes); 3765 STBTT__NOTUSED(num_nodes); 3788 3766 } 3789 3767 … … 3791 3769 { 3792 3770 int i; 3793 for (i =0; i < num_rects; ++i) {3771 for (i=0; i < num_rects; ++i) { 3794 3772 if (con->x + rects[i].w > con->width) { 3795 3773 con->x = 0; … … 3805 3783 con->bottom_y = con->y + rects[i].h; 3806 3784 } 3807 for ( ; i < num_rects; ++i)3785 for ( ; i < num_rects; ++i) 3808 3786 rects[i].was_packed = 0; 3809 3787 } … … 3819 3797 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) 3820 3798 { 3821 stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context),alloc_context);3799 stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); 3822 3800 int num_nodes = pw - padding; 3823 stbrp_node *nodes = (stbrp_node *)STBTT_malloc(sizeof(*nodes) * num_nodes,alloc_context);3801 stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); 3824 3802 3825 3803 if (context == NULL || nodes == NULL) { 3826 3804 if (context != NULL) STBTT_free(context, alloc_context); 3827 if (nodes != NULL) STBTT_free(nodes, alloc_context);3805 if (nodes != NULL) STBTT_free(nodes , alloc_context); 3828 3806 return 0; 3829 3807 } … … 3839 3817 spc->h_oversample = 1; 3840 3818 spc->v_oversample = 1; 3841 3842 stbrp_init_target(context, pw - padding, ph - padding, nodes, num_nodes); 3819 spc->skip_missing = 0; 3820 3821 stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); 3843 3822 3844 3823 if (pixels) … … 3848 3827 } 3849 3828 3850 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)3851 { 3852 STBTT_free(spc->nodes , spc->user_allocator_context);3829 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) 3830 { 3831 STBTT_free(spc->nodes , spc->user_allocator_context); 3853 3832 STBTT_free(spc->pack_info, spc->user_allocator_context); 3854 3833 } … … 3864 3843 } 3865 3844 3845 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) 3846 { 3847 spc->skip_missing = skip; 3848 } 3849 3866 3850 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) 3867 3851 … … 3872 3856 int j; 3873 3857 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze 3874 for (j =0; j < h; ++j) {3858 for (j=0; j < h; ++j) { 3875 3859 int i; 3876 3860 unsigned int total; … … 3881 3865 // make kernel_width a constant in common cases so compiler can optimize out the divide 3882 3866 switch (kernel_width) { 3883 case 2:3884 for (i =0; i <= safe_w; ++i) {3885 total += pixels[i] - buffer[i & STBTT__OVER_MASK];3886 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i];3887 pixels[i] = (unsigned char)(total / 2);3888 }3889 break;3890 case 3:3891 for (i =0; i <= safe_w; ++i) {3892 total += pixels[i] - buffer[i & STBTT__OVER_MASK];3893 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i];3894 pixels[i] = (unsigned char)(total / 3);3895 }3896 break;3897 case 4:3898 for (i =0; i <= safe_w; ++i) {3899 total += pixels[i] - buffer[i & STBTT__OVER_MASK];3900 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i];3901 pixels[i] = (unsigned char)(total / 4);3902 }3903 break;3904 case 5:3905 for (i =0; i <= safe_w; ++i) {3906 total += pixels[i] - buffer[i & STBTT__OVER_MASK];3907 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i];3908 pixels[i] = (unsigned char)(total / 5);3909 }3910 break;3911 default:3912 for (i =0; i <= safe_w; ++i) {3913 total += pixels[i] - buffer[i & STBTT__OVER_MASK];3914 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i];3915 pixels[i] = (unsigned char)(total / kernel_width);3916 }3917 break;3867 case 2: 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 / 2); 3872 } 3873 break; 3874 case 3: 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 / 3); 3879 } 3880 break; 3881 case 4: 3882 for (i=0; i <= safe_w; ++i) { 3883 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 3884 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 3885 pixels[i] = (unsigned char) (total / 4); 3886 } 3887 break; 3888 case 5: 3889 for (i=0; i <= safe_w; ++i) { 3890 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 3891 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 3892 pixels[i] = (unsigned char) (total / 5); 3893 } 3894 break; 3895 default: 3896 for (i=0; i <= safe_w; ++i) { 3897 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 3898 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 3899 pixels[i] = (unsigned char) (total / kernel_width); 3900 } 3901 break; 3918 3902 } 3919 3903 … … 3921 3905 STBTT_assert(pixels[i] == 0); 3922 3906 total -= buffer[i & STBTT__OVER_MASK]; 3923 pixels[i] = (unsigned char) (total / kernel_width);3907 pixels[i] = (unsigned char) (total / kernel_width); 3924 3908 } 3925 3909 … … 3934 3918 int j; 3935 3919 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze 3936 for (j =0; j < w; ++j) {3920 for (j=0; j < w; ++j) { 3937 3921 int i; 3938 3922 unsigned int total; … … 3943 3927 // make kernel_width a constant in common cases so compiler can optimize out the divide 3944 3928 switch (kernel_width) { 3945 case 2:3946 for (i =0; i <= safe_h; ++i) {3947 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];3948 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];3949 pixels[i*stride_in_bytes] = (unsigned char)(total / 2);3950 }3951 break;3952 case 3:3953 for (i =0; i <= safe_h; ++i) {3954 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];3955 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];3956 pixels[i*stride_in_bytes] = (unsigned char)(total / 3);3957 }3958 break;3959 case 4:3960 for (i =0; i <= safe_h; ++i) {3961 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];3962 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];3963 pixels[i*stride_in_bytes] = (unsigned char)(total / 4);3964 }3965 break;3966 case 5:3967 for (i =0; i <= safe_h; ++i) {3968 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];3969 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];3970 pixels[i*stride_in_bytes] = (unsigned char)(total / 5);3971 }3972 break;3973 default:3974 for (i =0; i <= safe_h; ++i) {3975 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];3976 buffer[(i +kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];3977 pixels[i*stride_in_bytes] = (unsigned char)(total / kernel_width);3978 }3979 break;3929 case 2: 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 / 2); 3934 } 3935 break; 3936 case 3: 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 / 3); 3941 } 3942 break; 3943 case 4: 3944 for (i=0; i <= safe_h; ++i) { 3945 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 3946 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 3947 pixels[i*stride_in_bytes] = (unsigned char) (total / 4); 3948 } 3949 break; 3950 case 5: 3951 for (i=0; i <= safe_h; ++i) { 3952 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 3953 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 3954 pixels[i*stride_in_bytes] = (unsigned char) (total / 5); 3955 } 3956 break; 3957 default: 3958 for (i=0; i <= safe_h; ++i) { 3959 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 3960 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 3961 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); 3962 } 3963 break; 3980 3964 } 3981 3965 … … 3983 3967 STBTT_assert(pixels[i*stride_in_bytes] == 0); 3984 3968 total -= buffer[i & STBTT__OVER_MASK]; 3985 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);3969 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); 3986 3970 } 3987 3971 … … 4005 3989 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) 4006 3990 { 4007 int i, j,k;4008 4009 k =0;4010 for (i =0; i < num_ranges; ++i) {3991 int i,j,k; 3992 3993 k=0; 3994 for (i=0; i < num_ranges; ++i) { 4011 3995 float fh = ranges[i].font_size; 4012 3996 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); 4013 ranges[i].h_oversample = (unsigned char) spc->h_oversample;4014 ranges[i].v_oversample = (unsigned char) spc->v_oversample;4015 for (j =0; j < ranges[i].num_chars; ++j) {4016 int x0, y0, x1,y1;3997 ranges[i].h_oversample = (unsigned char) spc->h_oversample; 3998 ranges[i].v_oversample = (unsigned char) spc->v_oversample; 3999 for (j=0; j < ranges[i].num_chars; ++j) { 4000 int x0,y0,x1,y1; 4017 4001 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; 4018 4002 int glyph = stbtt_FindGlyphIndex(info, codepoint); 4019 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, 4020 scale * spc->h_oversample, 4021 scale * spc->v_oversample, 4022 0, 0, 4023 &x0, &y0, &x1, &y1); 4024 rects[k].w = (stbrp_coord)(x1 - x0 + spc->padding + spc->h_oversample - 1); 4025 rects[k].h = (stbrp_coord)(y1 - y0 + spc->padding + spc->v_oversample - 1); 4003 if (glyph == 0 && spc->skip_missing) { 4004 rects[k].w = rects[k].h = 0; 4005 } else { 4006 stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, 4007 scale * spc->h_oversample, 4008 scale * spc->v_oversample, 4009 0,0, 4010 &x0,&y0,&x1,&y1); 4011 rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); 4012 rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); 4013 } 4026 4014 ++k; 4027 4015 } … … 4034 4022 { 4035 4023 stbtt_MakeGlyphBitmapSubpixel(info, 4036 output,4037 out_w - (prefilter_x - 1),4038 out_h - (prefilter_y - 1),4039 out_stride,4040 scale_x,4041 scale_y,4042 shift_x,4043 shift_y,4044 glyph);4024 output, 4025 out_w - (prefilter_x - 1), 4026 out_h - (prefilter_y - 1), 4027 out_stride, 4028 scale_x, 4029 scale_y, 4030 shift_x, 4031 shift_y, 4032 glyph); 4045 4033 4046 4034 if (prefilter_x > 1) … … 4057 4045 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) 4058 4046 { 4059 int i, j,k, return_value = 1;4047 int i,j,k, return_value = 1; 4060 4048 4061 4049 // save current values … … 4064 4052 4065 4053 k = 0; 4066 for (i =0; i < num_ranges; ++i) {4054 for (i=0; i < num_ranges; ++i) { 4067 4055 float fh = ranges[i].font_size; 4068 4056 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); 4069 float recip_h, recip_v, sub_x,sub_y;4057 float recip_h,recip_v,sub_x,sub_y; 4070 4058 spc->h_oversample = ranges[i].h_oversample; 4071 4059 spc->v_oversample = ranges[i].v_oversample; … … 4074 4062 sub_x = stbtt__oversample_shift(spc->h_oversample); 4075 4063 sub_y = stbtt__oversample_shift(spc->v_oversample); 4076 for (j =0; j < ranges[i].num_chars; ++j) {4064 for (j=0; j < ranges[i].num_chars; ++j) { 4077 4065 stbrp_rect *r = &rects[k]; 4078 if (r->was_packed ) {4066 if (r->was_packed && r->w != 0 && r->h != 0) { 4079 4067 stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; 4080 int advance, lsb, x0, y0, x1,y1;4068 int advance, lsb, x0,y0,x1,y1; 4081 4069 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; 4082 4070 int glyph = stbtt_FindGlyphIndex(info, codepoint); 4083 stbrp_coord pad = (stbrp_coord) spc->padding;4071 stbrp_coord pad = (stbrp_coord) spc->padding; 4084 4072 4085 4073 // pad on left and top … … 4090 4078 stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); 4091 4079 stbtt_GetGlyphBitmapBox(info, glyph, 4092 scale * spc->h_oversample,4093 scale * spc->v_oversample,4094 &x0, &y0, &x1,&y1);4080 scale * spc->h_oversample, 4081 scale * spc->v_oversample, 4082 &x0,&y0,&x1,&y1); 4095 4083 stbtt_MakeGlyphBitmapSubpixel(info, 4096 spc->pixels + r->x + r->y*spc->stride_in_bytes,4097 r->w - spc->h_oversample +1,4098 r->h - spc->v_oversample +1,4099 spc->stride_in_bytes,4100 scale * spc->h_oversample,4101 scale * spc->v_oversample,4102 0,0,4103 glyph);4084 spc->pixels + r->x + r->y*spc->stride_in_bytes, 4085 r->w - spc->h_oversample+1, 4086 r->h - spc->v_oversample+1, 4087 spc->stride_in_bytes, 4088 scale * spc->h_oversample, 4089 scale * spc->v_oversample, 4090 0,0, 4091 glyph); 4104 4092 4105 4093 if (spc->h_oversample > 1) 4106 4094 stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 4107 r->w, r->h, spc->stride_in_bytes,4108 spc->h_oversample);4095 r->w, r->h, spc->stride_in_bytes, 4096 spc->h_oversample); 4109 4097 4110 4098 if (spc->v_oversample > 1) 4111 4099 stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 4112 r->w, r->h, spc->stride_in_bytes, 4113 spc->v_oversample); 4114 4115 bc->x0 = (stbtt_int16)r->x; 4116 bc->y0 = (stbtt_int16)r->y; 4117 bc->x1 = (stbtt_int16)(r->x + r->w); 4118 bc->y1 = (stbtt_int16)(r->y + r->h); 4119 bc->xadvance = scale * advance; 4120 bc->xoff = (float)x0 * recip_h + sub_x; 4121 bc->yoff = (float)y0 * recip_v + sub_y; 4122 bc->xoff2 = (x0 + r->w) * recip_h + sub_x; 4123 bc->yoff2 = (y0 + r->h) * recip_v + sub_y; 4124 } 4125 else { 4100 r->w, r->h, spc->stride_in_bytes, 4101 spc->v_oversample); 4102 4103 bc->x0 = (stbtt_int16) r->x; 4104 bc->y0 = (stbtt_int16) r->y; 4105 bc->x1 = (stbtt_int16) (r->x + r->w); 4106 bc->y1 = (stbtt_int16) (r->y + r->h); 4107 bc->xadvance = scale * advance; 4108 bc->xoff = (float) x0 * recip_h + sub_x; 4109 bc->yoff = (float) y0 * recip_v + sub_y; 4110 bc->xoff2 = (x0 + r->w) * recip_h + sub_x; 4111 bc->yoff2 = (y0 + r->h) * recip_v + sub_y; 4112 } else { 4126 4113 return_value = 0; // if any fail, report failure 4127 4114 } … … 4140 4127 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) 4141 4128 { 4142 stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);4129 stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); 4143 4130 } 4144 4131 … … 4146 4133 { 4147 4134 stbtt_fontinfo info; 4148 int i, j, n, return_value = 1;4135 int i,j,n, return_value; // [DEAR IMGUI] removed = 1 4149 4136 //stbrp_context *context = (stbrp_context *) spc->pack_info; 4150 4137 stbrp_rect *rects; 4151 4138 4152 4139 // flag all characters as NOT packed 4153 for (i =0; i < num_ranges; ++i)4154 for (j =0; j < ranges[i].num_chars; ++j)4140 for (i=0; i < num_ranges; ++i) 4141 for (j=0; j < ranges[i].num_chars; ++j) 4155 4142 ranges[i].chardata_for_range[j].x0 = 4156 4143 ranges[i].chardata_for_range[j].y0 = … … 4159 4146 4160 4147 n = 0; 4161 for (i =0; i < num_ranges; ++i)4148 for (i=0; i < num_ranges; ++i) 4162 4149 n += ranges[i].num_chars; 4163 4164 rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);4150 4151 rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); 4165 4152 if (rects == NULL) 4166 4153 return 0; 4167 4154 4168 4155 info.userdata = spc->user_allocator_context; 4169 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, 4156 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); 4170 4157 4171 4158 n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); 4172 4159 4173 4160 stbtt_PackFontRangesPackRects(spc, rects, n); 4174 4161 4175 4162 return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); 4176 4163 … … 4180 4167 4181 4168 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, 4182 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)4169 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) 4183 4170 { 4184 4171 stbtt_pack_range range; 4185 4172 range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; 4186 4173 range.array_of_unicode_codepoints = NULL; 4187 range.num_chars = num_chars_in_range;4188 range.chardata_for_range = chardata_for_range;4189 range.font_size = font_size;4174 range.num_chars = num_chars_in_range; 4175 range.chardata_for_range = chardata_for_range; 4176 range.font_size = font_size; 4190 4177 return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); 4178 } 4179 4180 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) 4181 { 4182 int i_ascent, i_descent, i_lineGap; 4183 float scale; 4184 stbtt_fontinfo info; 4185 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); 4186 scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); 4187 stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); 4188 *ascent = (float) i_ascent * scale; 4189 *descent = (float) i_descent * scale; 4190 *lineGap = (float) i_lineGap * scale; 4191 4191 } 4192 4192 … … 4197 4197 4198 4198 if (align_to_integer) { 4199 float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);4200 float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);4199 float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); 4200 float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); 4201 4201 q->x0 = x; 4202 4202 q->y0 = y; 4203 4203 q->x1 = x + b->xoff2 - b->xoff; 4204 4204 q->y1 = y + b->yoff2 - b->yoff; 4205 } 4206 else { 4205 } else { 4207 4206 q->x0 = *xpos + b->xoff; 4208 4207 q->y0 = *ypos + b->yoff; … … 4229 4228 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]) 4230 4229 { 4231 float q0perp = q0[1] * ray[0] - q0[0] *ray[1];4232 float q1perp = q1[1] * ray[0] - q1[0] *ray[1];4233 float q2perp = q2[1] * ray[0] - q2[0] *ray[1];4234 float roperp = orig[1] * ray[0] - orig[0] *ray[1];4235 4236 float a = q0perp - 2 *q1perp + q2perp;4230 float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; 4231 float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; 4232 float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; 4233 float roperp = orig[1]*ray[0] - orig[0]*ray[1]; 4234 4235 float a = q0perp - 2*q1perp + q2perp; 4237 4236 float b = q1perp - q0perp; 4238 4237 float c = q0perp - roperp; … … 4242 4241 4243 4242 if (a != 0.0) { 4244 float discr = b * b - a *c;4243 float discr = b*b - a*c; 4245 4244 if (discr > 0.0) { 4246 4245 float rcpna = -1 / a; 4247 float d = (float) STBTT_sqrt(discr);4248 s0 = (b +d) * rcpna;4249 s1 = (b -d) * rcpna;4246 float d = (float) STBTT_sqrt(discr); 4247 s0 = (b+d) * rcpna; 4248 s1 = (b-d) * rcpna; 4250 4249 if (s0 >= 0.0 && s0 <= 1.0) 4251 4250 num_s = 1; … … 4255 4254 } 4256 4255 } 4257 } 4258 else { 4256 } else { 4259 4257 // 2*b*s + c = 0 4260 4258 // s = -c / (2*b) … … 4267 4265 return 0; 4268 4266 else { 4269 float rcp_len2 = 1 / (ray[0] * ray[0] + ray[1] *ray[1]);4267 float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); 4270 4268 float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; 4271 4269 4272 float q0d = q0[0] * rayn_x + q0[1] *rayn_y;4273 float q1d = q1[0] * rayn_x + q1[1] *rayn_y;4274 float q2d = q2[0] * rayn_x + q2[1] *rayn_y;4275 float rod = orig[0] * rayn_x + orig[1] *rayn_y;4270 float q0d = q0[0]*rayn_x + q0[1]*rayn_y; 4271 float q1d = q1[0]*rayn_x + q1[1]*rayn_y; 4272 float q2d = q2[0]*rayn_x + q2[1]*rayn_y; 4273 float rod = orig[0]*rayn_x + orig[1]*rayn_y; 4276 4274 4277 4275 float q10d = q1d - q0d; … … 4279 4277 float q0rd = q0d - rod; 4280 4278 4281 hits[0][0] = q0rd + s0 * (2.0f - 2.0f*s0)*q10d + s0 *s0*q20d;4282 hits[0][1] = a * s0 +b;4279 hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; 4280 hits[0][1] = a*s0+b; 4283 4281 4284 4282 if (num_s > 1) { 4285 hits[1][0] = q0rd + s1 * (2.0f - 2.0f*s1)*q10d + s1 *s1*q20d;4286 hits[1][1] = a * s1 +b;4283 hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; 4284 hits[1][1] = a*s1+b; 4287 4285 return 2; 4288 } 4289 else { 4286 } else { 4290 4287 return 1; 4291 4288 } … … 4306 4303 4307 4304 orig[0] = x; 4308 orig[1] = y;4305 //orig[1] = y; // [DEAR IMGUI] commmented double assignment 4309 4306 4310 4307 // make sure y never passes through a vertex of the shape 4311 y_frac = (float) STBTT_fmod(y, 1.0f);4308 y_frac = (float) STBTT_fmod(y, 1.0f); 4312 4309 if (y_frac < 0.01f) 4313 4310 y += 0.01f; … … 4317 4314 4318 4315 // test a ray from (-infinity,y) to (x,y) 4319 for (i =0; i < nverts; ++i) {4316 for (i=0; i < nverts; ++i) { 4320 4317 if (verts[i].type == STBTT_vline) { 4321 int x0 = (int) verts[i - 1].x, y0 = (int)verts[i -1].y;4322 int x1 = (int) verts[i].x, y1 = (int)verts[i].y;4323 if (y > STBTT_min(y0, y1) && y < STBTT_max(y0, y1) && x > STBTT_min(x0,x1)) {4324 float x_inter = (y - y0) / (y1 - y0) * (x1 -x0) + x0;4325 if (x_inter < x) 4318 int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; 4319 int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; 4320 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { 4321 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; 4322 if (x_inter < x) 4326 4323 winding += (y0 < y1) ? 1 : -1; 4327 4324 } 4328 4325 } 4329 4326 if (verts[i].type == STBTT_vcurve) { 4330 int x0 = (int) verts[i - 1].x, y0 = (int)verts[i - 1].y;4331 int x1 = (int) verts[i].cx, y1 = (int)verts[i].cy;4332 int x2 = (int) verts[i].x, y2 = (int)verts[i].y;4333 int ax = STBTT_min(x0, STBTT_min(x1, x2)), ay = STBTT_min(y0, STBTT_min(y1,y2));4334 int by = STBTT_max(y0, STBTT_max(y1,y2));4327 int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; 4328 int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; 4329 int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; 4330 int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); 4331 int by = STBTT_max(y0,STBTT_max(y1,y2)); 4335 4332 if (y > ay && y < by && x > ax) { 4336 float q0[2], q1[2],q2[2];4333 float q0[2],q1[2],q2[2]; 4337 4334 float hits[2][2]; 4338 4335 q0[0] = (float)x0; … … 4342 4339 q2[0] = (float)x2; 4343 4340 q2[1] = (float)y2; 4344 if (equal(q0, q1) || equal(q1,q2)) {4345 x0 = (int)verts[i -1].x;4346 y0 = (int)verts[i -1].y;4347 x1 = (int)verts[i ].x;4348 y1 = (int)verts[i ].y;4349 if (y > STBTT_min(y0, y1) && y < STBTT_max(y0, y1) && x > STBTT_min(x0,x1)) {4350 float x_inter = (y - y0) / (y1 - y0) * (x1 -x0) + x0;4351 if (x_inter < x) 4341 if (equal(q0,q1) || equal(q1,q2)) { 4342 x0 = (int)verts[i-1].x; 4343 y0 = (int)verts[i-1].y; 4344 x1 = (int)verts[i ].x; 4345 y1 = (int)verts[i ].y; 4346 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { 4347 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; 4348 if (x_inter < x) 4352 4349 winding += (y0 < y1) ? 1 : -1; 4353 4350 } 4354 } 4355 else { 4351 } else { 4356 4352 int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); 4357 4353 if (num_hits >= 1) … … 4362 4358 winding += (hits[1][1] < 0 ? -1 : 1); 4363 4359 } 4364 } 4360 } 4365 4361 } 4366 4362 } … … 4368 4364 } 4369 4365 4370 static float stbtt__cuberoot( float x)4366 static float stbtt__cuberoot( float x ) 4371 4367 { 4372 4368 if (x<0) 4373 return -(float) STBTT_pow(-x, 1.0f /3.0f);4369 return -(float) STBTT_pow(-x,1.0f/3.0f); 4374 4370 else 4375 return (float) STBTT_pow(x, 1.0f /3.0f);4371 return (float) STBTT_pow( x,1.0f/3.0f); 4376 4372 } 4377 4373 … … 4379 4375 static int stbtt__solve_cubic(float a, float b, float c, float* r) 4380 4376 { 4381 float s = -a / 3; 4382 float p = b - a * a / 3; 4383 float q = a * (2 * a*a - 9 * b) / 27 + c; 4384 float p3 = p * p*p; 4385 float d = q * q + 4 * p3 / 27; 4386 if (d >= 0) { 4387 float z = (float)STBTT_sqrt(d); 4388 float u = (-q + z) / 2; 4389 float v = (-q - z) / 2; 4390 u = stbtt__cuberoot(u); 4391 v = stbtt__cuberoot(v); 4392 r[0] = s + u + v; 4393 return 1; 4394 } 4395 else { 4396 float u = (float)STBTT_sqrt(-p / 3); 4397 float v = (float)STBTT_acos(-STBTT_sqrt(-27 / p3) * q / 2) / 3; // p3 must be negative, since d is negative 4398 float m = (float)STBTT_cos(v); 4399 float n = (float)STBTT_cos(v - 3.141592 / 2)*1.732050808f; 4400 r[0] = s + u * 2 * m; 4401 r[1] = s - u * (m + n); 4402 r[2] = s - u * (m - n); 4377 float s = -a / 3; 4378 float p = b - a*a / 3; 4379 float q = a * (2*a*a - 9*b) / 27 + c; 4380 float p3 = p*p*p; 4381 float d = q*q + 4*p3 / 27; 4382 if (d >= 0) { 4383 float z = (float) STBTT_sqrt(d); 4384 float u = (-q + z) / 2; 4385 float v = (-q - z) / 2; 4386 u = stbtt__cuberoot(u); 4387 v = stbtt__cuberoot(v); 4388 r[0] = s + u + v; 4389 return 1; 4390 } else { 4391 float u = (float) STBTT_sqrt(-p/3); 4392 float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative 4393 float m = (float) STBTT_cos(v); 4394 float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; 4395 r[0] = s + u * 2 * m; 4396 r[1] = s - u * (m + n); 4397 r[2] = s - u * (m - n); 4403 4398 4404 4399 //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? 4405 4400 //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); 4406 4401 //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); 4407 4402 return 3; 4408 4403 } 4409 4404 } … … 4412 4407 { 4413 4408 float scale_x = scale, scale_y = scale; 4414 int ix0, iy0, ix1,iy1;4415 int w, 4409 int ix0,iy0,ix1,iy1; 4410 int w,h; 4416 4411 unsigned char *data; 4417 4412 … … 4423 4418 } 4424 4419 4425 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f, 0.0f, &ix0, &iy0, &ix1,&iy1);4420 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); 4426 4421 4427 4422 // if empty, return NULL … … 4437 4432 h = (iy1 - iy0); 4438 4433 4439 if (width ) *width= w;4434 if (width ) *width = w; 4440 4435 if (height) *height = h; 4441 if (xoff ) *xoff= ix0;4442 if (yoff ) *yoff= iy0;4436 if (xoff ) *xoff = ix0; 4437 if (yoff ) *yoff = iy0; 4443 4438 4444 4439 // invert for y-downwards bitmaps 4445 4440 scale_y = -scale_y; 4446 4441 4447 4442 { 4448 int x, y, i,j;4443 int x,y,i,j; 4449 4444 float *precompute; 4450 4445 stbtt_vertex *verts; 4451 4446 int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); 4452 data = (unsigned char *) STBTT_malloc(w * h, info->userdata);4453 precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);4454 4455 for (i = 0, j = num_verts - 1; i < num_verts; j =i++) {4447 data = (unsigned char *) STBTT_malloc(w * h, info->userdata); 4448 precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); 4449 4450 for (i=0,j=num_verts-1; i < num_verts; j=i++) { 4456 4451 if (verts[i].type == STBTT_vline) { 4457 4452 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; 4458 4453 float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; 4459 float dist = (float) STBTT_sqrt((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 -y0));4454 float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); 4460 4455 precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; 4461 } 4462 else if (verts[i].type == STBTT_vcurve) { 4456 } else if (verts[i].type == STBTT_vcurve) { 4463 4457 float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; 4464 4458 float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; 4465 4459 float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; 4466 float bx = x0 - 2 * x1 + x2, by = y0 - 2 *y1 + y2;4467 float len2 = bx * bx + by *by;4460 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; 4461 float len2 = bx*bx + by*by; 4468 4462 if (len2 != 0.0f) 4469 precompute[i] = 1.0f / (bx*bx + by *by);4463 precompute[i] = 1.0f / (bx*bx + by*by); 4470 4464 else 4471 4465 precompute[i] = 0.0f; 4472 } 4473 else 4466 } else 4474 4467 precompute[i] = 0.0f; 4475 4468 } 4476 4469 4477 for (y =iy0; y < iy1; ++y) {4478 for (x =ix0; x < ix1; ++x) {4470 for (y=iy0; y < iy1; ++y) { 4471 for (x=ix0; x < ix1; ++x) { 4479 4472 float val; 4480 4473 float min_dist = 999999.0f; 4481 float sx = (float) x + 0.5f;4482 float sy = (float) y + 0.5f;4474 float sx = (float) x + 0.5f; 4475 float sy = (float) y + 0.5f; 4483 4476 float x_gspace = (sx / scale_x); 4484 4477 float y_gspace = (sy / scale_y); … … 4486 4479 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 4487 4480 4488 for (i =0; i < num_verts; ++i) {4481 for (i=0; i < num_verts; ++i) { 4489 4482 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; 4490 4483 4491 4484 // 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 4492 float dist2 = (x0 - sx)*(x0 - sx) + (y0 - sy)*(y0 -sy);4485 float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); 4493 4486 if (dist2 < min_dist*min_dist) 4494 min_dist = (float) STBTT_sqrt(dist2);4487 min_dist = (float) STBTT_sqrt(dist2); 4495 4488 4496 4489 if (verts[i].type == STBTT_vline) { 4497 float x1 = verts[i - 1].x*scale_x, y1 = verts[i -1].y*scale_y;4490 float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; 4498 4491 4499 4492 // coarse culling against bbox 4500 4493 //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && 4501 4494 // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) 4502 float dist = (float) STBTT_fabs((x1 - x0)*(y0 - sy) - (y1 - y0)*(x0 -sx)) * precompute[i];4495 float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; 4503 4496 STBTT_assert(i != 0); 4504 4497 if (dist < min_dist) { … … 4506 4499 // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) 4507 4500 // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) 4508 float dx = x1 - x0, dy = y1 -y0;4509 float px = x0 - sx, py = y0 -sy;4501 float dx = x1-x0, dy = y1-y0; 4502 float px = x0-sx, py = y0-sy; 4510 4503 // 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 4511 4504 // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve 4512 float t = -(px*dx + py * dy) / (dx*dx + dy *dy);4505 float t = -(px*dx + py*dy) / (dx*dx + dy*dy); 4513 4506 if (t >= 0.0f && t <= 1.0f) 4514 4507 min_dist = dist; 4515 4508 } 4516 } 4517 else if (verts[i].type == STBTT_vcurve) { 4518 float x2 = verts[i - 1].x *scale_x, y2 = verts[i - 1].y *scale_y; 4519 float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; 4520 float box_x0 = STBTT_min(STBTT_min(x0, x1), x2); 4521 float box_y0 = STBTT_min(STBTT_min(y0, y1), y2); 4522 float box_x1 = STBTT_max(STBTT_max(x0, x1), x2); 4523 float box_y1 = STBTT_max(STBTT_max(y0, y1), y2); 4509 } else if (verts[i].type == STBTT_vcurve) { 4510 float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; 4511 float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; 4512 float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); 4513 float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); 4514 float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); 4515 float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); 4524 4516 // coarse culling against bbox to avoid computing cubic unnecessarily 4525 if (sx > box_x0 - min_dist && sx < box_x1 + min_dist && sy > box_y0 - min_dist && sy < box_y1 +min_dist) {4526 int num =0;4527 float ax = x1 - x0, ay = y1 -y0;4528 float bx = x0 - 2 * x1 + x2, by = y0 - 2 *y1 + y2;4517 if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { 4518 int num=0; 4519 float ax = x1-x0, ay = y1-y0; 4520 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; 4529 4521 float mx = x0 - sx, my = y0 - sy; 4530 float res[3], px, py, t,it;4522 float res[3],px,py,t,it; 4531 4523 float a_inv = precompute[i]; 4532 4524 if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula 4533 float a = 3 * (ax*bx + ay *by);4534 float b = 2 * (ax*ax + ay * ay) + (mx*bx + my *by);4535 float c = mx * ax + my *ay;4525 float a = 3*(ax*bx + ay*by); 4526 float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); 4527 float c = mx*ax+my*ay; 4536 4528 if (a == 0.0) { // if a is 0, it's linear 4537 4529 if (b != 0.0) { 4538 res[num++] = -c /b;4530 res[num++] = -c/b; 4539 4531 } 4540 } 4541 else { 4542 float discriminant = b * b - 4 * a*c; 4532 } else { 4533 float discriminant = b*b - 4*a*c; 4543 4534 if (discriminant < 0) 4544 4535 num = 0; 4545 4536 else { 4546 float root = (float) STBTT_sqrt(discriminant);4547 res[0] = (-b - root) / (2 *a);4548 res[1] = (-b + root) / (2 *a);4537 float root = (float) STBTT_sqrt(discriminant); 4538 res[0] = (-b - root)/(2*a); 4539 res[1] = (-b + root)/(2*a); 4549 4540 num = 2; // don't bother distinguishing 1-solution case, as code below will still work 4550 4541 } 4551 4542 } 4552 } 4553 else { 4554 float b = 3 * (ax*bx + ay * by) * a_inv; // could precompute this as it doesn't depend on sample point 4555 float c = (2 * (ax*ax + ay * ay) + (mx*bx + my * by)) * a_inv; 4556 float d = (mx*ax + my * ay) * a_inv; 4543 } else { 4544 float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point 4545 float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; 4546 float d = (mx*ax+my*ay) * a_inv; 4557 4547 num = stbtt__solve_cubic(b, c, d, res); 4558 4548 } 4559 4549 if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { 4560 4550 t = res[0], it = 1.0f - t; 4561 px = it * it*x0 + 2 * t*it*x1 + t *t*x2;4562 py = it * it*y0 + 2 * t*it*y1 + t *t*y2;4563 dist2 = (px - sx)*(px - sx) + (py - sy)*(py -sy);4551 px = it*it*x0 + 2*t*it*x1 + t*t*x2; 4552 py = it*it*y0 + 2*t*it*y1 + t*t*y2; 4553 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); 4564 4554 if (dist2 < min_dist * min_dist) 4565 min_dist = (float) STBTT_sqrt(dist2);4555 min_dist = (float) STBTT_sqrt(dist2); 4566 4556 } 4567 4557 if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { 4568 4558 t = res[1], it = 1.0f - t; 4569 px = it * it*x0 + 2 * t*it*x1 + t *t*x2;4570 py = it * it*y0 + 2 * t*it*y1 + t *t*y2;4571 dist2 = (px - sx)*(px - sx) + (py - sy)*(py -sy);4559 px = it*it*x0 + 2*t*it*x1 + t*t*x2; 4560 py = it*it*y0 + 2*t*it*y1 + t*t*y2; 4561 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); 4572 4562 if (dist2 < min_dist * min_dist) 4573 min_dist = (float) STBTT_sqrt(dist2);4563 min_dist = (float) STBTT_sqrt(dist2); 4574 4564 } 4575 4565 if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { 4576 4566 t = res[2], it = 1.0f - t; 4577 px = it * it*x0 + 2 * t*it*x1 + t *t*x2;4578 py = it * it*y0 + 2 * t*it*y1 + t *t*y2;4579 dist2 = (px - sx)*(px - sx) + (py - sy)*(py -sy);4567 px = it*it*x0 + 2*t*it*x1 + t*t*x2; 4568 py = it*it*y0 + 2*t*it*y1 + t*t*y2; 4569 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); 4580 4570 if (dist2 < min_dist * min_dist) 4581 min_dist = (float) STBTT_sqrt(dist2);4571 min_dist = (float) STBTT_sqrt(dist2); 4582 4572 } 4583 4573 } … … 4591 4581 else if (val > 255) 4592 4582 val = 255; 4593 data[(y - iy0)*w + (x - ix0)] = (unsigned char)val;4583 data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; 4594 4584 } 4595 4585 } … … 4598 4588 } 4599 4589 return data; 4600 } 4590 } 4601 4591 4602 4592 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) … … 4616 4606 4617 4607 // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string 4618 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) 4619 { 4620 stbtt_int32 i =0;4608 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) 4609 { 4610 stbtt_int32 i=0; 4621 4611 4622 4612 // convert utf16 to utf8 and compare the results while converting 4623 4613 while (len2) { 4624 stbtt_uint16 ch = s2[0] *256 + s2[1];4614 stbtt_uint16 ch = s2[0]*256 + s2[1]; 4625 4615 if (ch < 0x80) { 4626 4616 if (i >= len1) return -1; 4627 4617 if (s1[i++] != ch) return -1; 4628 } 4629 else if (ch < 0x800) { 4630 if (i + 1 >= len1) return -1; 4618 } else if (ch < 0x800) { 4619 if (i+1 >= len1) return -1; 4631 4620 if (s1[i++] != 0xc0 + (ch >> 6)) return -1; 4632 4621 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; 4633 } 4634 else if (ch >= 0xd800 && ch < 0xdc00) { 4622 } else if (ch >= 0xd800 && ch < 0xdc00) { 4635 4623 stbtt_uint32 c; 4636 stbtt_uint16 ch2 = s2[2] *256 + s2[3];4637 if (i +3 >= len1) return -1;4624 stbtt_uint16 ch2 = s2[2]*256 + s2[3]; 4625 if (i+3 >= len1) return -1; 4638 4626 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; 4639 4627 if (s1[i++] != 0xf0 + (c >> 18)) return -1; 4640 4628 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; 4641 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;4642 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;4629 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; 4630 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; 4643 4631 s2 += 2; // plus another 2 below 4644 4632 len2 -= 2; 4645 } 4646 else if (ch >= 0xdc00 && ch < 0xe000) { 4633 } else if (ch >= 0xdc00 && ch < 0xe000) { 4647 4634 return -1; 4648 } 4649 else { 4650 if (i + 2 >= len1) return -1; 4635 } else { 4636 if (i+2 >= len1) return -1; 4651 4637 if (s1[i++] != 0xe0 + (ch >> 12)) return -1; 4652 4638 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; 4653 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;4639 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; 4654 4640 } 4655 4641 s2 += 2; … … 4659 4645 } 4660 4646 4661 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) 4662 { 4663 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*)s2, len2);4647 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) 4648 { 4649 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); 4664 4650 } 4665 4651 … … 4668 4654 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) 4669 4655 { 4670 stbtt_int32 i, count,stringOffset;4656 stbtt_int32 i,count,stringOffset; 4671 4657 stbtt_uint8 *fc = font->data; 4672 4658 stbtt_uint32 offset = font->fontstart; … … 4674 4660 if (!nm) return NULL; 4675 4661 4676 count = ttUSHORT(fc + nm +2);4677 stringOffset = nm + ttUSHORT(fc + nm +4);4678 for (i =0; i < count; ++i) {4662 count = ttUSHORT(fc+nm+2); 4663 stringOffset = nm + ttUSHORT(fc+nm+4); 4664 for (i=0; i < count; ++i) { 4679 4665 stbtt_uint32 loc = nm + 6 + 12 * i; 4680 if (platformID == ttUSHORT(fc + loc + 0) && encodingID == ttUSHORT(fc + loc +2)4681 && languageID == ttUSHORT(fc + loc + 4) && nameID == ttUSHORT(fc + loc +6)) {4682 *length = ttUSHORT(fc + loc +8);4683 return (const char *) (fc + stringOffset + ttUSHORT(fc + loc +10));4666 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) 4667 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { 4668 *length = ttUSHORT(fc+loc+8); 4669 return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); 4684 4670 } 4685 4671 } … … 4690 4676 { 4691 4677 stbtt_int32 i; 4692 stbtt_int32 count = ttUSHORT(fc + nm +2);4693 stbtt_int32 stringOffset = nm + ttUSHORT(fc + nm +4);4694 4695 for (i =0; i < count; ++i) {4678 stbtt_int32 count = ttUSHORT(fc+nm+2); 4679 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); 4680 4681 for (i=0; i < count; ++i) { 4696 4682 stbtt_uint32 loc = nm + 6 + 12 * i; 4697 stbtt_int32 id = ttUSHORT(fc + loc +6);4683 stbtt_int32 id = ttUSHORT(fc+loc+6); 4698 4684 if (id == target_id) { 4699 4685 // find the encoding 4700 stbtt_int32 platform = ttUSHORT(fc + loc + 0), encoding = ttUSHORT(fc + loc + 2), language = ttUSHORT(fc + loc +4);4686 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); 4701 4687 4702 4688 // is this a Unicode encoding? 4703 4689 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { 4704 stbtt_int32 slen = ttUSHORT(fc + loc +8);4705 stbtt_int32 off = ttUSHORT(fc + loc +10);4690 stbtt_int32 slen = ttUSHORT(fc+loc+8); 4691 stbtt_int32 off = ttUSHORT(fc+loc+10); 4706 4692 4707 4693 // check if there's a prefix match 4708 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc + stringOffset + off,slen);4694 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); 4709 4695 if (matchlen >= 0) { 4710 4696 // check for target_id+1 immediately following, with same encoding & language 4711 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) {4712 slen = ttUSHORT(fc + loc + 12 +8);4713 off = ttUSHORT(fc + loc + 12 +10);4697 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) { 4698 slen = ttUSHORT(fc+loc+12+8); 4699 off = ttUSHORT(fc+loc+12+10); 4714 4700 if (slen == 0) { 4715 4701 if (matchlen == nlen) 4716 4702 return 1; 4717 } 4718 else if (matchlen < nlen && name[matchlen] == ' ') { 4703 } else if (matchlen < nlen && name[matchlen] == ' ') { 4719 4704 ++matchlen; 4720 if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name + matchlen), nlen - matchlen, (char*)(fc + stringOffset + off),slen))4705 if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) 4721 4706 return 1; 4722 4707 } 4723 } 4724 else { 4708 } else { 4725 4709 // if nothing immediately following 4726 4710 if (matchlen == nlen) … … 4738 4722 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) 4739 4723 { 4740 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *)name);4741 stbtt_uint32 nm, 4742 if (!stbtt__isfont(fc +offset)) return 0;4724 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); 4725 stbtt_uint32 nm,hd; 4726 if (!stbtt__isfont(fc+offset)) return 0; 4743 4727 4744 4728 // check italics/bold/underline flags in macStyle... 4745 4729 if (flags) { 4746 4730 hd = stbtt__find_table(fc, offset, "head"); 4747 if ((ttUSHORT(fc + hd +44) & 7) != (flags & 7)) return 0;4731 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; 4748 4732 } 4749 4733 … … 4754 4738 // if we checked the macStyle flags, then just check the family and ignore the subfamily 4755 4739 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; 4756 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; 4757 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; 4758 } 4759 else { 4740 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; 4741 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; 4742 } else { 4760 4743 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; 4761 if (stbtt__matchpair(fc, nm, name, nlen, 1,2)) return 1;4762 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;4744 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; 4745 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; 4763 4746 } 4764 4747 … … 4769 4752 { 4770 4753 stbtt_int32 i; 4771 for (i = 0;;++i) {4754 for (i=0;;++i) { 4772 4755 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); 4773 4756 if (off < 0) return off; 4774 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*)name_utf8, flags))4757 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) 4775 4758 return off; 4776 4759 } … … 4783 4766 4784 4767 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, 4785 float pixel_height, unsigned char *pixels, int pw, int ph,4786 int first_char, int num_chars, stbtt_bakedchar *chardata)4787 { 4788 return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);4768 float pixel_height, unsigned char *pixels, int pw, int ph, 4769 int first_char, int num_chars, stbtt_bakedchar *chardata) 4770 { 4771 return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); 4789 4772 } 4790 4773 4791 4774 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) 4792 4775 { 4793 return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);4776 return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); 4794 4777 } 4795 4778 4796 4779 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) 4797 4780 { 4798 return stbtt_GetNumberOfFonts_internal((unsigned char *) data);4781 return stbtt_GetNumberOfFonts_internal((unsigned char *) data); 4799 4782 } 4800 4783 4801 4784 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) 4802 4785 { 4803 return stbtt_InitFont_internal(info, (unsigned char *) data, offset);4786 return stbtt_InitFont_internal(info, (unsigned char *) data, offset); 4804 4787 } 4805 4788 4806 4789 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) 4807 4790 { 4808 return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *)name, flags);4791 return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); 4809 4792 } 4810 4793 4811 4794 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) 4812 4795 { 4813 return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *)s2, len2);4796 return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); 4814 4797 } 4815 4798 … … 4884 4867 ALTERNATIVE A - MIT License 4885 4868 Copyright (c) 2017 Sean Barrett 4886 Permission is hereby granted, free of charge, to any person obtaining a copy of 4887 this software and associated documentation files (the "Software"), to deal in 4888 the Software without restriction, including without limitation the rights to 4889 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 4890 of the Software, and to permit persons to whom the Software is furnished to do 4869 Permission is hereby granted, free of charge, to any person obtaining a copy of 4870 this software and associated documentation files (the "Software"), to deal in 4871 the Software without restriction, including without limitation the rights to 4872 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 4873 of the Software, and to permit persons to whom the Software is furnished to do 4891 4874 so, subject to the following conditions: 4892 The above copyright notice and this permission notice shall be included in all 4875 The above copyright notice and this permission notice shall be included in all 4893 4876 copies or substantial portions of the Software. 4894 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4895 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4896 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4897 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4898 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4899 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4877 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4878 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4879 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4880 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4881 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 4882 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 4900 4883 SOFTWARE. 4901 4884 ------------------------------------------------------------------------------ 4902 4885 ALTERNATIVE B - Public Domain (www.unlicense.org) 4903 4886 This is free and unencumbered software released into the public domain. 4904 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 4905 software, either in source code form or as a compiled binary, for any purpose, 4887 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 4888 software, either in source code form or as a compiled binary, for any purpose, 4906 4889 commercial or non-commercial, and by any means. 4907 In jurisdictions that recognize copyright laws, the author or authors of this 4908 software dedicate any and all copyright interest in the software to the public 4909 domain. We make this dedication for the benefit of the public at large and to 4910 the detriment of our heirs and successors. We intend this dedication to be an 4911 overt act of relinquishment in perpetuity of all present and future rights to 4890 In jurisdictions that recognize copyright laws, the author or authors of this 4891 software dedicate any and all copyright interest in the software to the public 4892 domain. We make this dedication for the benefit of the public at large and to 4893 the detriment of our heirs and successors. We intend this dedication to be an 4894 overt act of relinquishment in perpetuity of all present and future rights to 4912 4895 this software under copyright law. 4913 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4914 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4915 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4916 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 4917 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 4896 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4897 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4898 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4899 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 4900 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 4918 4901 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 4919 4902 ------------------------------------------------------------------------------
Note:
See TracChangeset
for help on using the changeset viewer.