Rev 3002 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3002 | Rev 5517 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | // stb_truetype.h - v0.6c - public domain |
1 | // stb_truetype.h - v1.02 - public domain |
2 | // authored from 2009-2012 by Sean Barrett / RAD Game Tools |
2 | // authored from 2009-2014 by Sean Barrett / RAD Game Tools |
3 | // |
3 | // |
4 | // This library processes TrueType files: |
4 | // This library processes TrueType files: |
5 | // parse files |
5 | // parse files |
6 | // extract glyph metrics |
6 | // extract glyph metrics |
7 | // extract glyph shapes |
7 | // extract glyph shapes |
Line 19... | Line 19... | ||
19 | // ADDITIONAL CONTRIBUTORS |
19 | // ADDITIONAL CONTRIBUTORS |
20 | // |
20 | // |
21 | // Mikko Mononen: compound shape support, more cmap formats |
21 | // Mikko Mononen: compound shape support, more cmap formats |
22 | // Tor Andersson: kerning, subpixel rendering |
22 | // Tor Andersson: kerning, subpixel rendering |
23 | // |
23 | // |
24 | // Bug/warning reports: |
24 | // Bug/warning reports/fixes: |
25 | // "Zer" on mollyrocket (with fix) |
25 | // "Zer" on mollyrocket (with fix) |
26 | // Cass Everitt |
26 | // Cass Everitt |
27 | // stoiko (Haemimont Games) |
27 | // stoiko (Haemimont Games) |
28 | // Brian Hook |
28 | // Brian Hook |
29 | // Walter van Niftrik |
29 | // Walter van Niftrik |
- | 30 | // David Gow |
|
- | 31 | // David Given |
|
- | 32 | // Ivan-Assen Ivanov |
|
- | 33 | // Anthony Pesch |
|
- | 34 | // Johan Duparc |
|
- | 35 | // Hou Qiming |
|
- | 36 | // Fabian "ryg" Giesen |
|
- | 37 | // |
|
- | 38 | // Misc other: |
|
- | 39 | // Ryan Gordon |
|
30 | // |
40 | // |
31 | // VERSION HISTORY |
41 | // VERSION HISTORY |
32 | // |
42 | // |
- | 43 | // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ |
|
- | 44 | // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match |
|
- | 45 | // non-oversampled; STBTT_POINT_SIZE for packed case only |
|
- | 46 | // 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling |
|
- | 47 | // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) |
|
- | 48 | // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID |
|
- | 49 | // 0.8b (2014-07-07) fix a warning |
|
- | 50 | // 0.8 (2014-05-25) fix a few more warnings |
|
- | 51 | // 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back |
|
33 | // 0.6c (2012-07-24) improve documentation |
52 | // 0.6c (2012-07-24) improve documentation |
34 | // 0.6b (2012-07-20) fix a few more warnings |
53 | // 0.6b (2012-07-20) fix a few more warnings |
35 | // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, |
54 | // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, |
36 | // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty |
55 | // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty |
37 | // 0.5 (2011-12-09) bugfixes: |
56 | // 0.5 (2011-12-09) bugfixes: |
Line 44... | Line 63... | ||
44 | // codepoint-to-glyph conversion using table fmt=4 |
63 | // codepoint-to-glyph conversion using table fmt=4 |
45 | // stbtt_GetBakedQuad with non-square texture (Zer) |
64 | // stbtt_GetBakedQuad with non-square texture (Zer) |
46 | // updated Hello World! sample to use kerning and subpixel |
65 | // updated Hello World! sample to use kerning and subpixel |
47 | // fixed some warnings |
66 | // fixed some warnings |
48 | // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) |
67 | // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) |
49 | // userdata, malloc-from-userdata, non-zero fill (STB) |
68 | // userdata, malloc-from-userdata, non-zero fill (stb) |
50 | // 0.2 (2009-03-11) Fix unsigned/signed char warnings |
69 | // 0.2 (2009-03-11) Fix unsigned/signed char warnings |
51 | // 0.1 (2009-03-09) First public release |
70 | // 0.1 (2009-03-09) First public release |
52 | // |
71 | // |
53 | // LICENSE |
72 | // LICENSE |
54 | // |
73 | // |
Line 62... | Line 81... | ||
62 | // file, write: |
81 | // file, write: |
63 | // #define STB_TRUETYPE_IMPLEMENTATION |
82 | // #define STB_TRUETYPE_IMPLEMENTATION |
64 | // before the #include of this file. This expands out the actual |
83 | // before the #include of this file. This expands out the actual |
65 | // implementation into that C/C++ file. |
84 | // implementation into that C/C++ file. |
66 | // |
85 | // |
67 | // Look at the header-file sections below for the API, but here's a quick skim: |
- | |
68 | // |
- | |
69 | // Simple 3D API (don't ship this, but it's fine for tools and quick start, |
86 | // Simple 3D API (don't ship this, but it's fine for tools and quick start) |
70 | // and you can cut and paste from it to move to more advanced) |
- | |
71 | // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture |
87 | // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture |
72 | // stbtt_GetBakedQuad() -- compute quad to draw for a given char |
88 | // stbtt_GetBakedQuad() -- compute quad to draw for a given char |
73 | // |
89 | // |
- | 90 | // Improved 3D API (more shippable): |
|
- | 91 | // #include "stb_rect_pack.h" -- optional, but you really want it |
|
- | 92 | // stbtt_PackBegin() |
|
- | 93 | // stbtt_PackSetOversample() -- for improved quality on small fonts |
|
- | 94 | // stbtt_PackFontRanges() |
|
- | 95 | // stbtt_PackEnd() |
|
- | 96 | // stbtt_GetPackedQuad() |
|
- | 97 | // |
|
74 | // "Load" a font file from a memory buffer (you have to keep the buffer loaded) |
98 | // "Load" a font file from a memory buffer (you have to keep the buffer loaded) |
75 | // stbtt_InitFont() |
99 | // stbtt_InitFont() |
76 | // stbtt_GetFontOffsetForIndex() -- use for TTC font collections |
100 | // stbtt_GetFontOffsetForIndex() -- use for TTC font collections |
77 | // |
101 | // |
78 | // Render a unicode codepoint to a bitmap |
102 | // Render a unicode codepoint to a bitmap |
Line 222... | Line 246... | ||
222 | glBindTexture(GL_TEXTURE_2D, ftex); |
246 | glBindTexture(GL_TEXTURE_2D, ftex); |
223 | glBegin(GL_QUADS); |
247 | glBegin(GL_QUADS); |
224 | while (*text) { |
248 | while (*text) { |
225 | if (*text >= 32 && *text < 128) { |
249 | if (*text >= 32 && *text < 128) { |
226 | stbtt_aligned_quad q; |
250 | stbtt_aligned_quad q; |
227 | stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl,0=old d3d |
251 | stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 |
228 | glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); |
252 | glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); |
229 | glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); |
253 | glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); |
230 | glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); |
254 | glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); |
231 | glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); |
255 | glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); |
232 | } |
256 | } |
Line 291... | Line 315... | ||
291 | 315 | ||
292 | int main(int arg, char **argv) |
316 | int main(int arg, char **argv) |
293 | { |
317 | { |
294 | stbtt_fontinfo font; |
318 | stbtt_fontinfo font; |
295 | int i,j,ascent,baseline,ch=0; |
319 | int i,j,ascent,baseline,ch=0; |
296 | float scale, xpos=0; |
320 | float scale, xpos=2; // leave a little padding in case the character extends left |
Line 297... | Line 321... | ||
297 | char *text = "Heljo World!"; |
321 | char *text = "Heljo World!"; |
298 | 322 | ||
Line 337... | Line 361... | ||
337 | //// |
361 | //// |
338 | //// The following sections allow you to supply alternate definitions |
362 | //// The following sections allow you to supply alternate definitions |
339 | //// of C library functions used by stb_truetype. |
363 | //// of C library functions used by stb_truetype. |
Line 340... | Line 364... | ||
340 | 364 | ||
341 | #ifdef STB_TRUETYPE_IMPLEMENTATION |
- | |
342 | - | ||
343 | #define NULL 0 |
- | |
344 | typedef unsigned int size_t; |
365 | #ifdef STB_TRUETYPE_IMPLEMENTATION |
345 | // #define your own (u)stbtt_int8/16/32 before including to override this |
366 | // #define your own (u)stbtt_int8/16/32 before including to override this |
346 | #ifndef stbtt_uint8 |
367 | #ifndef stbtt_uint8 |
347 | typedef unsigned char stbtt_uint8; |
368 | typedef unsigned char stbtt_uint8; |
348 | typedef signed char stbtt_int8; |
369 | typedef signed char stbtt_int8; |
Line 353... | Line 374... | ||
353 | #endif |
374 | #endif |
Line 354... | Line 375... | ||
354 | 375 | ||
355 | typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; |
376 | typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; |
Line 356... | Line -... | ||
356 | typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; |
- | |
357 | - | ||
358 | - | ||
359 | - | ||
360 | #define THRESH 4 /* threshold for insertion */ |
- | |
361 | #define MTHRESH 6 /* threshold for median */ |
- | |
362 | - | ||
363 | static int (*qcmp)(const void *, const void *); /* the comparison routine */ |
- | |
364 | static int qsz; /* size of each record */ |
- | |
365 | static int thresh; /* THRESHold in chars */ |
- | |
366 | static int mthresh; /* MTHRESHold in chars */ |
- | |
367 | - | ||
368 | /* |
- | |
369 | * qst: |
- | |
370 | * Do a quicksort |
- | |
371 | * First, find the median element, and put that one in the first place as the |
- | |
372 | * discriminator. (This "median" is just the median of the first, last and |
- | |
373 | * middle elements). (Using this median instead of the first element is a big |
- | |
374 | * win). Then, the usual partitioning/swapping, followed by moving the |
- | |
375 | * discriminator into the right place. Then, figure out the sizes of the two |
- | |
376 | * partions, do the smaller one recursively and the larger one via a repeat of |
- | |
377 | * this code. Stopping when there are less than THRESH elements in a partition |
- | |
378 | * and cleaning up with an insertion sort (in our caller) is a huge win. |
- | |
379 | * All data swaps are done in-line, which is space-losing but time-saving. |
- | |
380 | * (And there are only three places where this is done). |
- | |
381 | */ |
- | |
382 | - | ||
383 | static void |
- | |
384 | qst(char *base, char *max) |
- | |
385 | { |
- | |
386 | char c, *i, *j, *jj; |
- | |
387 | int ii; |
- | |
388 | char *mid, *tmp; |
- | |
389 | int lo, hi; |
- | |
390 | - | ||
391 | /* |
- | |
392 | * At the top here, lo is the number of characters of elements in the |
- | |
393 | * current partition. (Which should be max - base). |
- | |
394 | * Find the median of the first, last, and middle element and make |
- | |
395 | * that the middle element. Set j to largest of first and middle. |
- | |
396 | * If max is larger than that guy, then it's that guy, else compare |
- | |
397 | * max with loser of first and take larger. Things are set up to |
- | |
398 | * prefer the middle, then the first in case of ties. |
- | |
399 | */ |
- | |
400 | lo = max - base; /* number of elements as chars */ |
- | |
401 | do { |
- | |
402 | mid = i = base + qsz * ((lo / qsz) >> 1); |
- | |
403 | if (lo >= mthresh) |
- | |
404 | { |
- | |
405 | j = (qcmp((jj = base), i) > 0 ? jj : i); |
- | |
406 | if (qcmp(j, (tmp = max - qsz)) > 0) |
- | |
407 | { |
- | |
408 | /* switch to first loser */ |
- | |
409 | j = (j == jj ? i : jj); |
- | |
410 | if (qcmp(j, tmp) < 0) |
- | |
411 | j = tmp; |
- | |
412 | } |
- | |
413 | if (j != i) |
- | |
414 | { |
- | |
415 | ii = qsz; |
- | |
416 | do { |
- | |
417 | c = *i; |
- | |
418 | *i++ = *j; |
- | |
419 | *j++ = c; |
- | |
420 | } while (--ii); |
- | |
421 | } |
- | |
422 | } |
- | |
423 | /* |
- | |
424 | * Semi-standard quicksort partitioning/swapping |
- | |
425 | */ |
- | |
426 | for (i = base, j = max - qsz; ; ) |
- | |
427 | { |
- | |
428 | while (i < mid && qcmp(i, mid) <= 0) |
- | |
429 | i += qsz; |
- | |
430 | while (j > mid) |
- | |
431 | { |
- | |
432 | if (qcmp(mid, j) <= 0) |
- | |
433 | { |
- | |
434 | j -= qsz; |
- | |
435 | continue; |
- | |
436 | } |
- | |
437 | tmp = i + qsz; /* value of i after swap */ |
- | |
438 | if (i == mid) |
- | |
439 | { |
- | |
440 | /* j <-> mid, new mid is j */ |
- | |
441 | mid = jj = j; |
- | |
442 | } |
- | |
443 | else |
- | |
444 | { |
- | |
445 | /* i <-> j */ |
- | |
446 | jj = j; |
- | |
447 | j -= qsz; |
- | |
448 | } |
- | |
449 | goto swap; |
- | |
450 | } |
- | |
451 | if (i == mid) |
- | |
452 | { |
- | |
453 | break; |
- | |
454 | } |
- | |
455 | else |
- | |
456 | { |
- | |
457 | /* i <-> mid, new mid is i */ |
- | |
458 | jj = mid; |
- | |
459 | tmp = mid = i; /* value of i after swap */ |
- | |
460 | j -= qsz; |
- | |
461 | } |
- | |
462 | swap: |
- | |
463 | ii = qsz; |
- | |
464 | do { |
- | |
465 | c = *i; |
- | |
466 | *i++ = *jj; |
- | |
467 | *jj++ = c; |
- | |
468 | } while (--ii); |
- | |
469 | i = tmp; |
- | |
470 | } |
- | |
471 | /* |
- | |
472 | * Look at sizes of the two partitions, do the smaller |
- | |
473 | * one first by recursion, then do the larger one by |
- | |
474 | * making sure lo is its size, base and max are update |
- | |
475 | * correctly, and branching back. But only repeat |
- | |
476 | * (recursively or by branching) if the partition is |
- | |
477 | * of at least size THRESH. |
- | |
478 | */ |
- | |
479 | i = (j = mid) + qsz; |
- | |
480 | if ((lo = j - base) <= (hi = max - i)) |
- | |
481 | { |
- | |
482 | if (lo >= thresh) |
- | |
483 | qst(base, j); |
- | |
484 | base = i; |
- | |
485 | lo = hi; |
- | |
486 | } |
- | |
487 | else |
- | |
488 | { |
- | |
489 | if (hi >= thresh) |
- | |
490 | qst(i, max); |
- | |
491 | max = j; |
- | |
492 | } |
- | |
493 | } while (lo >= thresh); |
- | |
494 | } |
- | |
495 | - | ||
496 | /* |
- | |
497 | * qsort: |
- | |
498 | * First, set up some global parameters for qst to share. Then, quicksort |
- | |
499 | * with qst(), and then a cleanup insertion sort ourselves. Sound simple? |
- | |
500 | * It's not... |
- | |
501 | */ |
- | |
502 | - | ||
503 | void |
- | |
504 | qsort_g(void *base0, size_t n, size_t size, int (*compar)(const void *, const void *)) |
- | |
505 | { |
- | |
506 | char *base = (char *)base0; |
- | |
507 | char c, *i, *j, *lo, *hi; |
- | |
508 | char *min, *max; |
- | |
509 | - | ||
510 | if (n <= 1) |
- | |
511 | return; |
- | |
512 | qsz = size; |
- | |
513 | qcmp = compar; |
- | |
514 | thresh = qsz * THRESH; |
- | |
515 | mthresh = qsz * MTHRESH; |
- | |
516 | max = base + n * qsz; |
- | |
517 | if (n >= THRESH) |
- | |
518 | { |
- | |
519 | qst(base, max); |
- | |
520 | hi = base + thresh; |
- | |
521 | } |
- | |
522 | else |
- | |
523 | { |
- | |
524 | hi = max; |
- | |
525 | } |
- | |
526 | /* |
- | |
527 | * First put smallest element, which must be in the first THRESH, in |
- | |
528 | * the first position as a sentinel. This is done just by searching |
- | |
529 | * the first THRESH elements (or the first n if n < THRESH), finding |
- | |
530 | * the min, and swapping it into the first position. |
- | |
531 | */ |
- | |
532 | for (j = lo = base; (lo += qsz) < hi; ) |
- | |
533 | if (qcmp(j, lo) > 0) |
- | |
534 | j = lo; |
- | |
535 | if (j != base) |
- | |
536 | { |
- | |
537 | /* swap j into place */ |
- | |
538 | for (i = base, hi = base + qsz; i < hi; ) |
- | |
539 | { |
- | |
540 | c = *j; |
- | |
541 | *j++ = *i; |
- | |
542 | *i++ = c; |
- | |
543 | } |
- | |
544 | } |
- | |
545 | /* |
- | |
546 | * With our sentinel in place, we now run the following hyper-fast |
- | |
547 | * insertion sort. For each remaining element, min, from [1] to [n-1], |
- | |
548 | * set hi to the index of the element AFTER which this one goes. |
- | |
549 | * Then, do the standard insertion sort shift on a character at a time |
- | |
550 | * basis for each element in the frob. |
- | |
551 | */ |
- | |
552 | for (min = base; (hi = min += qsz) < max; ) |
- | |
553 | { |
- | |
554 | while (qcmp(hi -= qsz, min) > 0) |
- | |
555 | /* void */; |
- | |
556 | if ((hi += qsz) != min) { |
- | |
557 | for (lo = min + qsz; --lo >= min; ) |
- | |
558 | { |
- | |
559 | c = *lo; |
- | |
560 | for (i = j = lo; (j -= qsz) >= hi; i = j) |
- | |
561 | *i = *j; |
- | |
562 | *i = c; |
- | |
563 | } |
- | |
564 | } |
- | |
565 | } |
- | |
566 | } |
- | |
567 | 377 | typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; |
|
568 | 378 | ||
569 | // #define your own STBTT_sort() to override this to avoid qsort |
379 | // #define your own STBTT_sort() to override this to avoid qsort |
570 | #ifndef STBTT_sort |
380 | #ifndef STBTT_sort |
571 | //#include |
381 | #include |
Line 572... | Line -... | ||
572 | #define STBTT_sort(data,num_items,item_size,compare_func) qsort_g(data,num_items,item_size,compare_func) |
- | |
573 | #endif |
- | |
574 | - | ||
575 | asm ("_floor: \n\t" |
- | |
576 | "pushl %ebp\n\t" |
- | |
577 | "movl %esp,%ebp\n\t" |
- | |
578 | "subl $8,%esp\n\t" |
- | |
579 | "fstcw -4(%ebp)\n\t" |
- | |
580 | "fwait\n\t" |
- | |
581 | "movw -4(%ebp),%ax\n\t" |
- | |
582 | "andw $0xf3ff,%ax\n\t" |
- | |
583 | "orw $0x0400,%ax\n\t" |
- | |
584 | "movw %ax,-2(%ebp)\n\t" |
- | |
585 | "fldcw -2(%ebp)\n\t" |
- | |
586 | "fldl 8(%ebp)\n\t" |
- | |
587 | "frndint\n\t" |
- | |
588 | "fldcw -4(%ebp)\n\t" |
- | |
589 | "movl %ebp,%esp\n\t" |
- | |
590 | "popl %ebp\n\t" |
- | |
591 | "ret"); |
- | |
592 | - | ||
593 | - | ||
594 | int i_floor (float x) { |
- | |
595 | int z; |
- | |
596 | z=x; |
- | |
597 | if (z+1>x) {return z;} else {return (z+1);} |
- | |
598 | - | ||
599 | } |
- | |
600 | - | ||
601 | int i_ceil (float x) { |
- | |
602 | int z; |
- | |
603 | z=x; |
- | |
604 | if (z>x) {return z;} else {return (z+1);} |
- | |
605 | - | ||
606 | } |
- | |
607 | - | ||
608 | - | ||
609 | double |
- | |
610 | sqrt (double x) |
- | |
611 | { |
- | |
612 | if (x < 0.0F ) |
- | |
613 | { |
- | |
614 | return -1; |
- | |
615 | } |
- | |
616 | else |
- | |
617 | { |
- | |
618 | double res; |
- | |
619 | asm ("fsqrt" : "=t" (res) : "0" (x)); |
- | |
620 | return res; |
- | |
621 | } |
382 | #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func) |
622 | } |
383 | #endif |
623 | 384 | ||
624 | // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h |
385 | // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h |
625 | #ifndef STBTT_ifloor |
386 | #ifndef STBTT_ifloor |
626 | // #include |
387 | #include |
Line 627... | Line -... | ||
627 | #define STBTT_ifloor(x) ((int) i_floor(x)) |
- | |
628 | #define STBTT_iceil(x) ((int) i_ceil(x)) |
- | |
629 | #endif |
388 | #define STBTT_ifloor(x) ((int) floor(x)) |
630 | - | ||
631 | static inline void *zmalloc(size_t size) { |
- | |
632 | void *val; __asm__ __volatile__( "int $0x40" :"=a"(val) :"a"(68),"b"(12),"c"(size)); |
389 | #define STBTT_iceil(x) ((int) ceil(x)) |
633 | return val; } |
- | |
634 | 390 | #endif |
|
635 | 391 | ||
Line 636... | Line 392... | ||
636 | void zfree(void *p) |
392 | #ifndef STBTT_sqrt |
637 | { |
393 | #include |
638 | asm ("int $0x40"::"a"(68), "b"(13), "c"(p) ); |
394 | #define STBTT_sqrt(x) sqrt(x) |
639 | } |
395 | #endif |
640 | 396 | ||
641 | // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h |
397 | // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h |
Line 642... | Line -... | ||
642 | #ifndef STBTT_malloc |
- | |
643 | //#include |
- | |
644 | #define STBTT_malloc(x,u) zmalloc(x) |
398 | #ifndef STBTT_malloc |
645 | #define STBTT_free(x,u) zfree(x) |
399 | #include |
646 | #endif |
400 | #define STBTT_malloc(x,u) ((void)(u),malloc(x)) |
647 | 401 | #define STBTT_free(x,u) ((void)(u),free(x)) |
|
Line 648... | Line -... | ||
648 | #define assert_g(ignore)((void) 0) |
- | |
649 | - | ||
650 | #ifndef STBTT_assert |
- | |
651 | //#include |
- | |
652 | #define STBTT_assert(x) assert_g(x) |
- | |
653 | #endif |
- | |
654 | - | ||
655 | - | ||
656 | int strlen_g(const char* string) |
- | |
657 | { |
- | |
658 | int i; |
402 | #endif |
659 | i=0; |
403 | |
660 | while (*string++) i++; |
404 | #ifndef STBTT_assert |
661 | return i; |
405 | #include |
Line 662... | Line -... | ||
662 | } |
- | |
663 | - | ||
664 | - | ||
665 | #ifndef STBTT_strlen |
- | |
666 | //#include |
- | |
667 | #define STBTT_strlen(x) strlen_g(x) |
- | |
668 | #endif |
- | |
669 | - | ||
670 | void* zmemset(void *mem, int c, unsigned size) |
- | |
671 | { |
- | |
672 | unsigned i; |
- | |
673 | - | ||
674 | for ( i = 0; i < size; i++ ) |
- | |
675 | *((char *)mem+i) = (char) c; |
- | |
676 | - | ||
677 | return 0; |
- | |
678 | } |
- | |
679 | - | ||
680 | - | ||
681 | void* zmemcpy(void *dst, const void *src, unsigned size) |
- | |
682 | { |
- | |
683 | - | ||
684 | unsigned i; |
406 | #define STBTT_assert(x) assert(x) |
685 | 407 | #endif |
|
686 | for ( i = 0; i < size; i++) |
408 | |
687 | *(char *)(dst+i) = *(char *)(src+i); |
409 | #ifndef STBTT_strlen |
688 | 410 | #include |
|
689 | return 0; |
411 | #define STBTT_strlen(x) strlen(x) |
Line 690... | Line 412... | ||
690 | } |
412 | #endif |
691 | 413 | ||
Line 753... | Line 475... | ||
753 | // see discussion of "BASELINE" above. |
475 | // see discussion of "BASELINE" above. |
754 | // |
476 | // |
755 | // It's inefficient; you might want to c&p it and optimize it. |
477 | // It's inefficient; you might want to c&p it and optimize it. |
Line -... | Line 478... | ||
- | 478 | ||
- | 479 | ||
- | 480 | ||
- | 481 | ////////////////////////////////////////////////////////////////////////////// |
|
- | 482 | // |
|
- | 483 | // NEW TEXTURE BAKING API |
|
- | 484 | // |
|
- | 485 | // This provides options for packing multiple fonts into one atlas, not |
|
- | 486 | // perfectly but better than nothing. |
|
- | 487 | ||
- | 488 | typedef struct |
|
- | 489 | { |
|
- | 490 | unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap |
|
- | 491 | float xoff,yoff,xadvance; |
|
- | 492 | float xoff2,yoff2; |
|
- | 493 | } stbtt_packedchar; |
|
- | 494 | ||
- | 495 | typedef struct stbtt_pack_context stbtt_pack_context; |
|
- | 496 | ||
- | 497 | extern int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); |
|
- | 498 | // Initializes a packing context stored in the passed-in stbtt_pack_context. |
|
- | 499 | // Future calls using this context will pack characters into the bitmap passed |
|
- | 500 | // in here: a 1-channel bitmap that is weight x height. stride_in_bytes is |
|
- | 501 | // the distance from one row to the next (or 0 to mean they are packed tightly |
|
- | 502 | // together). "padding" is // the amount of padding to leave between each |
|
- | 503 | // character (normally you want '1' for bitmaps you'll use as textures with |
|
- | 504 | // bilinear filtering). |
|
- | 505 | // |
|
- | 506 | // Returns 0 on failure, 1 on success. |
|
- | 507 | ||
- | 508 | extern void stbtt_PackEnd (stbtt_pack_context *spc); |
|
- | 509 | // Cleans up the packing context and frees all memory. |
|
- | 510 | ||
- | 511 | #define STBTT_POINT_SIZE(x) (-(x)) |
|
- | 512 | ||
- | 513 | extern int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, |
|
- | 514 | int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); |
|
- | 515 | // Creates character bitmaps from the font_index'th font found in fontdata (use |
|
- | 516 | // font_index=0 if you don't know what that is). It creates num_chars_in_range |
|
- | 517 | // bitmaps for characters with unicode values starting at first_unicode_char_in_range |
|
- | 518 | // and increasing. Data for how to render them is stored in chardata_for_range; |
|
- | 519 | // pass these to stbtt_GetPackedQuad to get back renderable quads. |
|
- | 520 | // |
|
- | 521 | // font_size is the full height of the character from ascender to descender, |
|
- | 522 | // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed |
|
- | 523 | // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() |
|
- | 524 | // and pass that result as 'font_size': |
|
- | 525 | // ..., 20 , ... // font max minus min y is 20 pixels tall |
|
- | 526 | // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall |
|
- | 527 | ||
- | 528 | typedef struct |
|
- | 529 | { |
|
- | 530 | float font_size; |
|
- | 531 | int first_unicode_char_in_range; |
|
- | 532 | int num_chars_in_range; |
|
- | 533 | stbtt_packedchar *chardata_for_range; // output |
|
- | 534 | } stbtt_pack_range; |
|
- | 535 | ||
- | 536 | extern int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); |
|
- | 537 | // Creates character bitmaps from multiple ranges of characters stored in |
|
- | 538 | // ranges. This will usually create a better-packed bitmap than multiple |
|
- | 539 | // calls to stbtt_PackFontRange. |
|
- | 540 | ||
- | 541 | ||
- | 542 | extern void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); |
|
- | 543 | // Oversampling a font increases the quality by allowing higher-quality subpixel |
|
- | 544 | // positioning, and is especially valuable at smaller text sizes. |
|
- | 545 | // |
|
- | 546 | // This function sets the amount of oversampling for all following calls to |
|
- | 547 | // stbtt_PackFontRange(s). The default (no oversampling) is achieved by |
|
- | 548 | // h_oversample=1, v_oversample=1. The total number of pixels required is |
|
- | 549 | // h_oversample*v_oversample larger than the default; for example, 2x2 |
|
- | 550 | // oversampling requires 4x the storage of 1x1. For best results, render |
|
- | 551 | // oversampled textures with bilinear filtering. Look at the readme in |
|
- | 552 | // stb/tests/oversample for information about oversampled fonts |
|
- | 553 | ||
- | 554 | extern void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above |
|
- | 555 | int char_index, // character to display |
|
- | 556 | float *xpos, float *ypos, // pointers to current position in screen pixel space |
|
- | 557 | stbtt_aligned_quad *q, // output: quad to draw |
|
- | 558 | int align_to_integer); |
|
- | 559 | ||
- | 560 | // this is an opaque structure that you shouldn't mess with which holds |
|
- | 561 | // all the context needed from PackBegin to PackEnd. |
|
- | 562 | struct stbtt_pack_context { |
|
- | 563 | void *user_allocator_context; |
|
- | 564 | void *pack_info; |
|
- | 565 | int width; |
|
- | 566 | int height; |
|
- | 567 | int stride_in_bytes; |
|
- | 568 | int padding; |
|
- | 569 | unsigned int h_oversample, v_oversample; |
|
- | 570 | unsigned char *pixels; |
|
- | 571 | void *nodes; |
|
756 | 572 | }; |
|
757 | 573 | ||
758 | ////////////////////////////////////////////////////////////////////////////// |
574 | ////////////////////////////////////////////////////////////////////////////// |
759 | // |
575 | // |
760 | // FONT LOADING |
576 | // FONT LOADING |
Line 838... | Line 654... | ||
838 | // advanceWidth is the offset from the current horizontal position to the next horizontal position |
654 | // advanceWidth is the offset from the current horizontal position to the next horizontal position |
839 | // these are expressed in unscaled coordinates |
655 | // these are expressed in unscaled coordinates |
Line 840... | Line 656... | ||
840 | 656 | ||
841 | extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); |
657 | extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); |
842 | // an additional amount to add to the 'advance' value between ch1 and ch2 |
- | |
Line 843... | Line 658... | ||
843 | // @TODO; for now always returns 0! |
658 | // an additional amount to add to the 'advance' value between ch1 and ch2 |
844 | 659 | ||
Line 845... | Line 660... | ||
845 | extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); |
660 | extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); |
Line 880... | Line 695... | ||
880 | 695 | ||
881 | extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); |
696 | extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); |
882 | extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); |
697 | extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); |
883 | // returns # of vertices and fills *vertices with the pointer to them |
698 | // returns # of vertices and fills *vertices with the pointer to them |
- | 699 | // these are expressed in "unscaled" coordinates |
|
- | 700 | // |
|
- | 701 | // The shape is a series of countours. Each one starts with |
|
- | 702 | // a STBTT_moveto, then consists of a series of mixed |
|
- | 703 | // STBTT_lineto and STBTT_curveto segments. A lineto |
|
- | 704 | // draws a line from previous endpoint to its x,y; a curveto |
|
- | 705 | // draws a quadratic bezier from previous endpoint to |
|
Line 884... | Line 706... | ||
884 | // these are expressed in "unscaled" coordinates |
706 | // its x,y, using cx,cy as the bezier control point. |
885 | 707 | ||
Line 886... | Line 708... | ||
886 | extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); |
708 | extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); |
Line 1054... | Line 876... | ||
1054 | //// |
876 | //// |
1055 | //// |
877 | //// |
Line 1056... | Line 878... | ||
1056 | 878 | ||
Line -... | Line 879... | ||
- | 879 | #ifdef STB_TRUETYPE_IMPLEMENTATION |
|
- | 880 | ||
- | 881 | #ifndef STBTT_MAX_OVERSAMPLE |
|
- | 882 | #define STBTT_MAX_OVERSAMPLE 8 |
|
- | 883 | #endif |
|
- | 884 | ||
1057 | #ifdef STB_TRUETYPE_IMPLEMENTATION |
885 | typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; |
1058 | 886 | ||
1059 | ////////////////////////////////////////////////////////////////////////// |
887 | ////////////////////////////////////////////////////////////////////////// |
1060 | // |
888 | // |
Line 1066... | Line 894... | ||
1066 | 894 | ||
1067 | #define ttBYTE(p) (* (stbtt_uint8 *) (p)) |
895 | #define ttBYTE(p) (* (stbtt_uint8 *) (p)) |
1068 | #define ttCHAR(p) (* (stbtt_int8 *) (p)) |
896 | #define ttCHAR(p) (* (stbtt_int8 *) (p)) |
Line -... | Line 897... | ||
- | 897 | #define ttFixed(p) ttLONG(p) |
|
Line 1069... | Line -... | ||
1069 | #define ttFixed(p) ttLONG(p) |
- | |
1070 | - | ||
1071 | - | ||
1072 | 898 | ||
1073 | //#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) |
899 | #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) |
1074 | /* |
900 | |
1075 | #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) |
901 | #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) |
1076 | #define ttSHORT(p) (* (stbtt_int16 *) (p)) |
902 | #define ttSHORT(p) (* (stbtt_int16 *) (p)) |
1077 | #define ttULONG(p) (* (stbtt_uint32 *) (p)) |
903 | #define ttULONG(p) (* (stbtt_uint32 *) (p)) |
Line 1078... | Line 904... | ||
1078 | #define ttLONG(p) (* (stbtt_int32 *) (p)) |
904 | #define ttLONG(p) (* (stbtt_int32 *) (p)) |
1079 | */ |
905 | |
1080 | //#else |
906 | #else |
1081 | 907 | ||
Line 1082... | Line 908... | ||
1082 | stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } |
908 | stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } |
Line 1083... | Line 909... | ||
1083 | stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } |
909 | stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } |
1084 | stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } |
910 | stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } |
Line 1085... | Line 911... | ||
1085 | stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } |
911 | stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } |
Line 1173... | Line 999... | ||
1173 | // MS/Unicode |
999 | // MS/Unicode |
1174 | info->index_map = cmap + ttULONG(data+encoding_record+4); |
1000 | info->index_map = cmap + ttULONG(data+encoding_record+4); |
1175 | break; |
1001 | break; |
1176 | } |
1002 | } |
1177 | break; |
1003 | break; |
- | 1004 | case STBTT_PLATFORM_ID_UNICODE: |
|
- | 1005 | // Mac/iOS has these |
|
- | 1006 | // all the encodingIDs are unicode, so we don't bother to check it |
|
- | 1007 | info->index_map = cmap + ttULONG(data+encoding_record+4); |
|
- | 1008 | break; |
|
1178 | } |
1009 | } |
1179 | } |
1010 | } |
1180 | if (info->index_map == 0) |
1011 | if (info->index_map == 0) |
1181 | return 0; |
1012 | return 0; |
Line 1224... | Line 1055... | ||
1224 | search += rangeShift*2; |
1055 | search += rangeShift*2; |
Line 1225... | Line 1056... | ||
1225 | 1056 | ||
1226 | // now decrement to bias correctly to find smallest |
1057 | // now decrement to bias correctly to find smallest |
1227 | search -= 2; |
1058 | search -= 2; |
1228 | while (entrySelector) { |
- | |
1229 | stbtt_uint16 start, end; |
1059 | while (entrySelector) { |
1230 | searchRange >>= 1; |
- | |
1231 | start = ttUSHORT(data + search + 2 + segcount*2 + 2); |
- | |
1232 | end = ttUSHORT(data + search + 2); |
1060 | searchRange >>= 1; |
1233 | start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2); |
1061 | start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2); |
1234 | end = ttUSHORT(data + search + searchRange*2); |
1062 | end = ttUSHORT(data + search + searchRange*2); |
1235 | if (unicode_codepoint > end) |
1063 | if (unicode_codepoint > end) |
1236 | search += searchRange*2; |
1064 | search += searchRange*2; |
Line 1252... | Line 1080... | ||
1252 | 1080 | ||
1253 | return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); |
1081 | return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); |
1254 | } else if (format == 12 || format == 13) { |
1082 | } else if (format == 12 || format == 13) { |
1255 | stbtt_uint32 ngroups = ttULONG(data+index_map+12); |
1083 | stbtt_uint32 ngroups = ttULONG(data+index_map+12); |
1256 | stbtt_int32 low,high; |
- | |
1257 | //stbtt_uint16 g = 0; |
1084 | stbtt_int32 low,high; |
1258 | low = 0; high = (stbtt_int32)ngroups; |
1085 | low = 0; high = (stbtt_int32)ngroups; |
1259 | // Binary search the right group. |
1086 | // Binary search the right group. |
1260 | while (low < high) { |
1087 | while (low < high) { |
1261 | stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high |
1088 | stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high |
Line 1533... | Line 1360... | ||
1533 | mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; |
1360 | mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; |
1534 | mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; |
1361 | mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; |
1535 | } |
1362 | } |
Line 1536... | Line 1363... | ||
1536 | 1363 | ||
1537 | // Find transformation scales. |
1364 | // Find transformation scales. |
1538 | m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); |
1365 | m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); |
Line 1539... | Line 1366... | ||
1539 | n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); |
1366 | n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); |
1540 | 1367 | ||
1541 | // Get indexed glyph. |
1368 | // Get indexed glyph. |
1542 | comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); |
1369 | comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); |
Line 1557... | Line 1384... | ||
1557 | if (!tmp) { |
1384 | if (!tmp) { |
1558 | if (vertices) STBTT_free(vertices, info->userdata); |
1385 | if (vertices) STBTT_free(vertices, info->userdata); |
1559 | if (comp_verts) STBTT_free(comp_verts, info->userdata); |
1386 | if (comp_verts) STBTT_free(comp_verts, info->userdata); |
1560 | return 0; |
1387 | return 0; |
1561 | } |
1388 | } |
1562 | //if (num_vertices > 0) STBTT_memset(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); |
- | |
1563 | if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));//lev |
1389 | if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); |
1564 | STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); |
1390 | STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); |
1565 | if (vertices) STBTT_free(vertices, info->userdata); |
1391 | if (vertices) STBTT_free(vertices, info->userdata); |
1566 | vertices = tmp; |
1392 | vertices = tmp; |
1567 | STBTT_free(comp_verts, info->userdata); |
1393 | STBTT_free(comp_verts, info->userdata); |
1568 | num_vertices += comp_num_verts; |
1394 | num_vertices += comp_num_verts; |
Line 1673... | Line 1499... | ||
1673 | // |
1499 | // |
Line 1674... | Line 1500... | ||
1674 | 1500 | ||
1675 | 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) |
1501 | 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) |
1676 | { |
1502 | { |
1677 | int x0,y0,x1,y1; |
1503 | int x0,y0,x1,y1; |
1678 | if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) |
1504 | if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { |
- | 1505 | // e.g. space character |
|
- | 1506 | if (ix0) *ix0 = 0; |
|
- | 1507 | if (iy0) *iy0 = 0; |
|
- | 1508 | if (ix1) *ix1 = 0; |
|
- | 1509 | if (iy1) *iy1 = 0; |
|
1679 | x0=y0=x1=y1=0; // e.g. space character |
1510 | } else { |
1680 | // now move to integral bboxes (treating pixels as little squares, what pixels get touched)? |
1511 | // move to integral bboxes (treating pixels as little squares, what pixels get touched)? |
1681 | if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x + shift_x); |
1512 | if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); |
1682 | if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y + shift_y); |
1513 | if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); |
1683 | if (ix1) *ix1 = STBTT_iceil (x1 * scale_x + shift_x); |
1514 | if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); |
- | 1515 | if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); |
|
1684 | if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y + shift_y); |
1516 | } |
- | 1517 | } |
|
1685 | } |
1518 | |
1686 | void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) |
1519 | void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) |
1687 | { |
1520 | { |
1688 | stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); |
1521 | stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); |
Line 1927... | Line 1760... | ||
1927 | if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { |
1760 | if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { |
1928 | e[n].invert = 1; |
1761 | e[n].invert = 1; |
1929 | a=j,b=k; |
1762 | a=j,b=k; |
1930 | } |
1763 | } |
1931 | e[n].x0 = p[a].x * scale_x + shift_x; |
1764 | e[n].x0 = p[a].x * scale_x + shift_x; |
1932 | e[n].y0 = p[a].y * y_scale_inv * vsubsample + shift_y; |
1765 | e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; |
1933 | e[n].x1 = p[b].x * scale_x + shift_x; |
1766 | e[n].x1 = p[b].x * scale_x + shift_x; |
1934 | e[n].y1 = p[b].y * y_scale_inv * vsubsample + shift_y; |
1767 | e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; |
1935 | ++n; |
1768 | ++n; |
1936 | } |
1769 | } |
1937 | } |
1770 | } |
Line 1938... | Line 1771... | ||
1938 | 1771 | ||
Line 2071... | Line 1904... | ||
2071 | if (scale_y == 0) { |
1904 | if (scale_y == 0) { |
2072 | if (scale_x == 0) return NULL; |
1905 | if (scale_x == 0) return NULL; |
2073 | scale_y = scale_x; |
1906 | scale_y = scale_x; |
2074 | } |
1907 | } |
Line 2075... | Line 1908... | ||
2075 | 1908 | ||
Line 2076... | Line 1909... | ||
2076 | stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1); |
1909 | stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); |
2077 | 1910 | ||
2078 | // now we get the size |
1911 | // now we get the size |
2079 | gbm.w = (ix1 - ix0); |
1912 | gbm.w = (ix1 - ix0); |
Line 2159... | Line 1992... | ||
2159 | stbtt_bakedchar *chardata) |
1992 | stbtt_bakedchar *chardata) |
2160 | { |
1993 | { |
2161 | float scale; |
1994 | float scale; |
2162 | int x,y,bottom_y, i; |
1995 | int x,y,bottom_y, i; |
2163 | stbtt_fontinfo f; |
1996 | stbtt_fontinfo f; |
2164 | stbtt_InitFont(&f, data, offset); |
1997 | if (!stbtt_InitFont(&f, data, offset)) |
- | 1998 | return -1; |
|
2165 | STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels |
1999 | STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels |
2166 | x=y=1; |
2000 | x=y=1; |
2167 | bottom_y = 1; |
2001 | bottom_y = 1; |
Line 2168... | Line 2002... | ||
2168 | 2002 | ||
Line 2187... | Line 2021... | ||
2187 | chardata[i].x1 = (stbtt_int16) (x + gw); |
2021 | chardata[i].x1 = (stbtt_int16) (x + gw); |
2188 | chardata[i].y1 = (stbtt_int16) (y + gh); |
2022 | chardata[i].y1 = (stbtt_int16) (y + gh); |
2189 | chardata[i].xadvance = scale * advance; |
2023 | chardata[i].xadvance = scale * advance; |
2190 | chardata[i].xoff = (float) x0; |
2024 | chardata[i].xoff = (float) x0; |
2191 | chardata[i].yoff = (float) y0; |
2025 | chardata[i].yoff = (float) y0; |
2192 | x = x + gw + 2; |
2026 | x = x + gw + 1; |
2193 | if (y+gh+2 > bottom_y) |
2027 | if (y+gh+1 > bottom_y) |
2194 | bottom_y = y+gh+2; |
2028 | bottom_y = y+gh+1; |
2195 | } |
2029 | } |
2196 | return bottom_y; |
2030 | return bottom_y; |
2197 | } |
2031 | } |
Line 2198... | Line 2032... | ||
2198 | 2032 | ||
Line 2217... | Line 2051... | ||
2217 | *xpos += b->xadvance; |
2051 | *xpos += b->xadvance; |
2218 | } |
2052 | } |
Line 2219... | Line 2053... | ||
2219 | 2053 | ||
2220 | ////////////////////////////////////////////////////////////////////////////// |
2054 | ////////////////////////////////////////////////////////////////////////////// |
- | 2055 | // |
|
- | 2056 | // rectangle packing replacement routines if you don't have stb_rect_pack.h |
|
- | 2057 | // |
|
- | 2058 | ||
- | 2059 | #ifndef STB_RECT_PACK_VERSION |
|
- | 2060 | #ifdef _MSC_VER |
|
- | 2061 | #define STBTT__NOTUSED(v) (void)(v) |
|
- | 2062 | #else |
|
- | 2063 | #define STBTT__NOTUSED(v) (void)sizeof(v) |
|
- | 2064 | #endif |
|
- | 2065 | ||
- | 2066 | typedef int stbrp_coord; |
|
- | 2067 | ||
- | 2068 | //////////////////////////////////////////////////////////////////////////////////// |
|
- | 2069 | // // |
|
- | 2070 | // // |
|
- | 2071 | // COMPILER WARNING ?!?!? // |
|
- | 2072 | // // |
|
- | 2073 | // // |
|
- | 2074 | // if you get a compile warning due to these symbols being defined more than // |
|
- | 2075 | // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // |
|
- | 2076 | // // |
|
- | 2077 | //////////////////////////////////////////////////////////////////////////////////// |
|
- | 2078 | ||
- | 2079 | typedef struct |
|
- | 2080 | { |
|
- | 2081 | int width,height; |
|
- | 2082 | int x,y,bottom_y; |
|
- | 2083 | } stbrp_context; |
|
- | 2084 | ||
- | 2085 | typedef struct |
|
- | 2086 | { |
|
- | 2087 | unsigned char x; |
|
- | 2088 | } stbrp_node; |
|
- | 2089 | ||
- | 2090 | typedef struct |
|
- | 2091 | { |
|
- | 2092 | stbrp_coord x,y; |
|
- | 2093 | int id,w,h,was_packed; |
|
- | 2094 | } stbrp_rect; |
|
- | 2095 | ||
- | 2096 | static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) |
|
- | 2097 | { |
|
- | 2098 | con->width = pw; |
|
- | 2099 | con->height = ph; |
|
- | 2100 | con->x = 0; |
|
- | 2101 | con->y = 0; |
|
- | 2102 | con->bottom_y = 0; |
|
- | 2103 | STBTT__NOTUSED(nodes); |
|
- | 2104 | STBTT__NOTUSED(num_nodes); |
|
- | 2105 | } |
|
- | 2106 | ||
- | 2107 | static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) |
|
- | 2108 | { |
|
- | 2109 | int i; |
|
- | 2110 | for (i=0; i < num_rects; ++i) { |
|
- | 2111 | if (con->x + rects[i].w > con->width) { |
|
- | 2112 | con->x = 0; |
|
- | 2113 | con->y = con->bottom_y; |
|
- | 2114 | } |
|
- | 2115 | if (con->y + rects[i].h > con->height) |
|
- | 2116 | break; |
|
- | 2117 | rects[i].x = con->x; |
|
- | 2118 | rects[i].y = con->y; |
|
- | 2119 | rects[i].was_packed = 1; |
|
- | 2120 | con->x += rects[i].w; |
|
- | 2121 | if (con->y + rects[i].h > con->bottom_y) |
|
- | 2122 | con->bottom_y = con->y + rects[i].h; |
|
- | 2123 | } |
|
- | 2124 | for ( ; i < num_rects; ++i) |
|
- | 2125 | rects[i].was_packed = 0; |
|
- | 2126 | } |
|
- | 2127 | #endif |
|
- | 2128 | ||
- | 2129 | ////////////////////////////////////////////////////////////////////////////// |
|
- | 2130 | // |
|
- | 2131 | // bitmap baking |
|
- | 2132 | // |
|
- | 2133 | // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If |
|
- | 2134 | // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. |
|
- | 2135 | ||
- | 2136 | int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) |
|
- | 2137 | { |
|
- | 2138 | stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); |
|
- | 2139 | int num_nodes = pw - padding; |
|
- | 2140 | stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); |
|
- | 2141 | ||
- | 2142 | if (context == NULL || nodes == NULL) { |
|
- | 2143 | if (context != NULL) STBTT_free(context, alloc_context); |
|
- | 2144 | if (nodes != NULL) STBTT_free(nodes , alloc_context); |
|
- | 2145 | return 0; |
|
- | 2146 | } |
|
- | 2147 | ||
- | 2148 | spc->user_allocator_context = alloc_context; |
|
- | 2149 | spc->width = pw; |
|
- | 2150 | spc->height = ph; |
|
- | 2151 | spc->pixels = pixels; |
|
- | 2152 | spc->pack_info = context; |
|
- | 2153 | spc->nodes = nodes; |
|
- | 2154 | spc->padding = padding; |
|
- | 2155 | spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; |
|
- | 2156 | spc->h_oversample = 1; |
|
- | 2157 | spc->v_oversample = 1; |
|
- | 2158 | ||
- | 2159 | stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); |
|
- | 2160 | ||
- | 2161 | STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels |
|
- | 2162 | ||
- | 2163 | return 1; |
|
- | 2164 | } |
|
- | 2165 | ||
- | 2166 | void stbtt_PackEnd (stbtt_pack_context *spc) |
|
- | 2167 | { |
|
- | 2168 | STBTT_free(spc->nodes , spc->user_allocator_context); |
|
- | 2169 | STBTT_free(spc->pack_info, spc->user_allocator_context); |
|
- | 2170 | } |
|
- | 2171 | ||
- | 2172 | void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) |
|
- | 2173 | { |
|
- | 2174 | STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); |
|
- | 2175 | STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); |
|
- | 2176 | if (h_oversample <= STBTT_MAX_OVERSAMPLE) |
|
- | 2177 | spc->h_oversample = h_oversample; |
|
- | 2178 | if (v_oversample <= STBTT_MAX_OVERSAMPLE) |
|
- | 2179 | spc->v_oversample = v_oversample; |
|
- | 2180 | } |
|
- | 2181 | ||
- | 2182 | #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) |
|
- | 2183 | ||
- | 2184 | static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) |
|
- | 2185 | { |
|
- | 2186 | unsigned char buffer[STBTT_MAX_OVERSAMPLE]; |
|
- | 2187 | int safe_w = w - kernel_width; |
|
- | 2188 | int j; |
|
- | 2189 | for (j=0; j < h; ++j) { |
|
- | 2190 | int i; |
|
- | 2191 | unsigned int total; |
|
- | 2192 | STBTT_memset(buffer, 0, kernel_width); |
|
- | 2193 | ||
- | 2194 | total = 0; |
|
- | 2195 | ||
- | 2196 | // make kernel_width a constant in common cases so compiler can optimize out the divide |
|
- | 2197 | switch (kernel_width) { |
|
- | 2198 | case 2: |
|
- | 2199 | for (i=0; i <= safe_w; ++i) { |
|
- | 2200 | total += pixels[i] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2201 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; |
|
- | 2202 | pixels[i] = (unsigned char) (total / 2); |
|
- | 2203 | } |
|
- | 2204 | break; |
|
- | 2205 | case 3: |
|
- | 2206 | for (i=0; i <= safe_w; ++i) { |
|
- | 2207 | total += pixels[i] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2208 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; |
|
- | 2209 | pixels[i] = (unsigned char) (total / 3); |
|
- | 2210 | } |
|
- | 2211 | break; |
|
- | 2212 | case 4: |
|
- | 2213 | for (i=0; i <= safe_w; ++i) { |
|
- | 2214 | total += pixels[i] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2215 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; |
|
- | 2216 | pixels[i] = (unsigned char) (total / 4); |
|
- | 2217 | } |
|
- | 2218 | break; |
|
- | 2219 | default: |
|
- | 2220 | for (i=0; i <= safe_w; ++i) { |
|
- | 2221 | total += pixels[i] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2222 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; |
|
- | 2223 | pixels[i] = (unsigned char) (total / kernel_width); |
|
- | 2224 | } |
|
- | 2225 | break; |
|
- | 2226 | } |
|
- | 2227 | ||
- | 2228 | for (; i < w; ++i) { |
|
- | 2229 | STBTT_assert(pixels[i] == 0); |
|
- | 2230 | total -= buffer[i & STBTT__OVER_MASK]; |
|
- | 2231 | pixels[i] = (unsigned char) (total / kernel_width); |
|
- | 2232 | } |
|
- | 2233 | ||
- | 2234 | pixels += stride_in_bytes; |
|
- | 2235 | } |
|
- | 2236 | } |
|
- | 2237 | ||
- | 2238 | static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) |
|
- | 2239 | { |
|
- | 2240 | unsigned char buffer[STBTT_MAX_OVERSAMPLE]; |
|
- | 2241 | int safe_h = h - kernel_width; |
|
- | 2242 | int j; |
|
- | 2243 | for (j=0; j < w; ++j) { |
|
- | 2244 | int i; |
|
- | 2245 | unsigned int total; |
|
- | 2246 | STBTT_memset(buffer, 0, kernel_width); |
|
- | 2247 | ||
- | 2248 | total = 0; |
|
- | 2249 | ||
- | 2250 | // make kernel_width a constant in common cases so compiler can optimize out the divide |
|
- | 2251 | switch (kernel_width) { |
|
- | 2252 | case 2: |
|
- | 2253 | for (i=0; i <= safe_h; ++i) { |
|
- | 2254 | total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2255 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; |
|
- | 2256 | pixels[i*stride_in_bytes] = (unsigned char) (total / 2); |
|
- | 2257 | } |
|
- | 2258 | break; |
|
- | 2259 | case 3: |
|
- | 2260 | for (i=0; i <= safe_h; ++i) { |
|
- | 2261 | total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2262 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; |
|
- | 2263 | pixels[i*stride_in_bytes] = (unsigned char) (total / 3); |
|
- | 2264 | } |
|
- | 2265 | break; |
|
- | 2266 | case 4: |
|
- | 2267 | for (i=0; i <= safe_h; ++i) { |
|
- | 2268 | total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2269 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; |
|
- | 2270 | pixels[i*stride_in_bytes] = (unsigned char) (total / 4); |
|
- | 2271 | } |
|
- | 2272 | break; |
|
- | 2273 | default: |
|
- | 2274 | for (i=0; i <= safe_h; ++i) { |
|
- | 2275 | total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; |
|
- | 2276 | buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; |
|
- | 2277 | pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); |
|
- | 2278 | } |
|
- | 2279 | break; |
|
- | 2280 | } |
|
- | 2281 | ||
- | 2282 | for (; i < h; ++i) { |
|
- | 2283 | STBTT_assert(pixels[i*stride_in_bytes] == 0); |
|
- | 2284 | total -= buffer[i & STBTT__OVER_MASK]; |
|
- | 2285 | pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); |
|
- | 2286 | } |
|
- | 2287 | ||
- | 2288 | pixels += 1; |
|
- | 2289 | } |
|
- | 2290 | } |
|
- | 2291 | ||
- | 2292 | static float stbtt__oversample_shift(int oversample) |
|
- | 2293 | { |
|
- | 2294 | if (!oversample) |
|
- | 2295 | return 0.0f; |
|
- | 2296 | ||
- | 2297 | // The prefilter is a box filter of width "oversample", |
|
- | 2298 | // which shifts phase by (oversample - 1)/2 pixels in |
|
- | 2299 | // oversampled space. We want to shift in the opposite |
|
- | 2300 | // direction to counter this. |
|
- | 2301 | return (float)-(oversample - 1) / (2.0f * (float)oversample); |
|
- | 2302 | } |
|
- | 2303 | ||
- | 2304 | int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) |
|
- | 2305 | { |
|
- | 2306 | stbtt_fontinfo info; |
|
- | 2307 | float recip_h = 1.0f / spc->h_oversample; |
|
- | 2308 | float recip_v = 1.0f / spc->v_oversample; |
|
- | 2309 | float sub_x = stbtt__oversample_shift(spc->h_oversample); |
|
- | 2310 | float sub_y = stbtt__oversample_shift(spc->v_oversample); |
|
- | 2311 | int i,j,k,n, return_value = 1; |
|
- | 2312 | stbrp_context *context = (stbrp_context *) spc->pack_info; |
|
- | 2313 | stbrp_rect *rects; |
|
- | 2314 | ||
- | 2315 | // flag all characters as NOT packed |
|
- | 2316 | for (i=0; i < num_ranges; ++i) |
|
- | 2317 | for (j=0; j < ranges[i].num_chars_in_range; ++j) |
|
- | 2318 | ranges[i].chardata_for_range[j].x0 = |
|
- | 2319 | ranges[i].chardata_for_range[j].y0 = |
|
- | 2320 | ranges[i].chardata_for_range[j].x1 = |
|
- | 2321 | ranges[i].chardata_for_range[j].y1 = 0; |
|
- | 2322 | ||
- | 2323 | n = 0; |
|
- | 2324 | for (i=0; i < num_ranges; ++i) |
|
- | 2325 | n += ranges[i].num_chars_in_range; |
|
- | 2326 | ||
- | 2327 | rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); |
|
- | 2328 | if (rects == NULL) |
|
- | 2329 | return 0; |
|
- | 2330 | ||
- | 2331 | stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); |
|
- | 2332 | k=0; |
|
- | 2333 | for (i=0; i < num_ranges; ++i) { |
|
- | 2334 | float fh = ranges[i].font_size; |
|
- | 2335 | float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh); |
|
- | 2336 | for (j=0; j < ranges[i].num_chars_in_range; ++j) { |
|
- | 2337 | int x0,y0,x1,y1; |
|
- | 2338 | stbtt_GetCodepointBitmapBoxSubpixel(&info, ranges[i].first_unicode_char_in_range + j, |
|
- | 2339 | scale * spc->h_oversample, |
|
- | 2340 | scale * spc->v_oversample, |
|
- | 2341 | 0,0, |
|
- | 2342 | &x0,&y0,&x1,&y1); |
|
- | 2343 | rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); |
|
- | 2344 | rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); |
|
- | 2345 | ++k; |
|
- | 2346 | } |
|
- | 2347 | } |
|
- | 2348 | ||
- | 2349 | stbrp_pack_rects(context, rects, k); |
|
- | 2350 | ||
- | 2351 | k = 0; |
|
- | 2352 | for (i=0; i < num_ranges; ++i) { |
|
- | 2353 | float fh = ranges[i].font_size; |
|
- | 2354 | float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh); |
|
- | 2355 | for (j=0; j < ranges[i].num_chars_in_range; ++j) { |
|
- | 2356 | stbrp_rect *r = &rects[k]; |
|
- | 2357 | if (r->was_packed) { |
|
- | 2358 | stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; |
|
- | 2359 | int advance, lsb, x0,y0,x1,y1; |
|
- | 2360 | int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j); |
|
- | 2361 | stbrp_coord pad = (stbrp_coord) spc->padding; |
|
- | 2362 | ||
- | 2363 | // pad on left and top |
|
- | 2364 | r->x += pad; |
|
- | 2365 | r->y += pad; |
|
- | 2366 | r->w -= pad; |
|
- | 2367 | r->h -= pad; |
|
- | 2368 | stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb); |
|
- | 2369 | stbtt_GetGlyphBitmapBox(&info, glyph, |
|
- | 2370 | scale * spc->h_oversample, |
|
- | 2371 | scale * spc->v_oversample, |
|
- | 2372 | &x0,&y0,&x1,&y1); |
|
- | 2373 | stbtt_MakeGlyphBitmapSubpixel(&info, |
|
- | 2374 | spc->pixels + r->x + r->y*spc->stride_in_bytes, |
|
- | 2375 | r->w - spc->h_oversample+1, |
|
- | 2376 | r->h - spc->v_oversample+1, |
|
- | 2377 | spc->stride_in_bytes, |
|
- | 2378 | scale * spc->h_oversample, |
|
- | 2379 | scale * spc->v_oversample, |
|
- | 2380 | 0,0, |
|
- | 2381 | glyph); |
|
- | 2382 | ||
- | 2383 | if (spc->h_oversample > 1) |
|
- | 2384 | stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, |
|
- | 2385 | r->w, r->h, spc->stride_in_bytes, |
|
- | 2386 | spc->h_oversample); |
|
- | 2387 | ||
- | 2388 | if (spc->v_oversample > 1) |
|
- | 2389 | stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, |
|
- | 2390 | r->w, r->h, spc->stride_in_bytes, |
|
- | 2391 | spc->v_oversample); |
|
- | 2392 | ||
- | 2393 | bc->x0 = (stbtt_int16) r->x; |
|
- | 2394 | bc->y0 = (stbtt_int16) r->y; |
|
- | 2395 | bc->x1 = (stbtt_int16) (r->x + r->w); |
|
- | 2396 | bc->y1 = (stbtt_int16) (r->y + r->h); |
|
- | 2397 | bc->xadvance = scale * advance; |
|
- | 2398 | bc->xoff = (float) x0 * recip_h + sub_x; |
|
- | 2399 | bc->yoff = (float) y0 * recip_v + sub_y; |
|
- | 2400 | bc->xoff2 = (x0 + r->w) * recip_h + sub_x; |
|
- | 2401 | bc->yoff2 = (y0 + r->h) * recip_v + sub_y; |
|
- | 2402 | } else { |
|
- | 2403 | return_value = 0; // if any fail, report failure |
|
- | 2404 | } |
|
- | 2405 | ||
- | 2406 | ++k; |
|
- | 2407 | } |
|
- | 2408 | } |
|
- | 2409 | ||
- | 2410 | zfree(rects); /////////////////////////////// |
|
- | 2411 | ||
- | 2412 | return return_value; |
|
- | 2413 | } |
|
- | 2414 | ||
- | 2415 | int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, |
|
- | 2416 | int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) |
|
- | 2417 | { |
|
- | 2418 | stbtt_pack_range range; |
|
- | 2419 | range.first_unicode_char_in_range = first_unicode_char_in_range; |
|
- | 2420 | range.num_chars_in_range = num_chars_in_range; |
|
- | 2421 | range.chardata_for_range = chardata_for_range; |
|
- | 2422 | range.font_size = font_size; |
|
- | 2423 | return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); |
|
- | 2424 | } |
|
- | 2425 | ||
- | 2426 | void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) |
|
- | 2427 | { |
|
- | 2428 | float ipw = 1.0f / pw, iph = 1.0f / ph; |
|
- | 2429 | stbtt_packedchar *b = chardata + char_index; |
|
- | 2430 | ||
- | 2431 | if (align_to_integer) { |
|
- | 2432 | float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5); |
|
- | 2433 | float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5); |
|
- | 2434 | q->x0 = x; |
|
- | 2435 | q->y0 = y; |
|
- | 2436 | q->x1 = x + b->xoff2 - b->xoff; |
|
- | 2437 | q->y1 = y + b->yoff2 - b->yoff; |
|
- | 2438 | } else { |
|
- | 2439 | q->x0 = *xpos + b->xoff; |
|
- | 2440 | q->y0 = *ypos + b->yoff; |
|
- | 2441 | q->x1 = *xpos + b->xoff2; |
|
- | 2442 | q->y1 = *ypos + b->yoff2; |
|
- | 2443 | } |
|
- | 2444 | ||
- | 2445 | q->s0 = b->x0 * ipw; |
|
- | 2446 | q->t0 = b->y0 * iph; |
|
- | 2447 | q->s1 = b->x1 * ipw; |
|
- | 2448 | q->t1 = b->y1 * iph; |
|
- | 2449 | ||
- | 2450 | *xpos += b->xadvance; |
|
- | 2451 | } |
|
- | 2452 | ||
- | 2453 | ||
- | 2454 | ////////////////////////////////////////////////////////////////////////////// |
|
2221 | // |
2455 | // |
2222 | // font name matching -- recommended not to use this |
2456 | // font name matching -- recommended not to use this |
Line 2223... | Line 2457... | ||
2223 | // |
2457 | // |
2224 | 2458 | ||
Line 2303... | Line 2537... | ||
2303 | // find the encoding |
2537 | // find the encoding |
2304 | stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); |
2538 | stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); |
Line 2305... | Line 2539... | ||
2305 | 2539 | ||
2306 | // is this a Unicode encoding? |
2540 | // is this a Unicode encoding? |
- | 2541 | if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { |
|
2307 | if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { |
2542 | stbtt_int32 slen = ttUSHORT(fc+loc+8); |
Line 2308... | Line 2543... | ||
2308 | stbtt_int32 slen = ttUSHORT(fc+loc+8), off = ttUSHORT(fc+loc+10); |
2543 | stbtt_int32 off = ttUSHORT(fc+loc+10); |
2309 | 2544 | ||
2310 | // check if there's a prefix match |
2545 | // check if there's a prefix match |
2311 | stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); |
2546 | stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); |
2312 | if (matchlen >= 0) { |
2547 | if (matchlen >= 0) { |
- | 2548 | // check for target_id+1 immediately following, with same encoding & language |
|
2313 | // check for target_id+1 immediately following, with same encoding & language |
2549 | 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) { |
2314 | 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) { |
2550 | slen = ttUSHORT(fc+loc+12+8); |
2315 | stbtt_int32 slen = ttUSHORT(fc+loc+12+8), off = ttUSHORT(fc+loc+12+10); |
2551 | off = ttUSHORT(fc+loc+12+10); |
2316 | if (slen == 0) { |
2552 | if (slen == 0) { |
2317 | if (matchlen == nlen) |
2553 | if (matchlen == nlen) |
2318 | return 1; |
2554 | return 1; |