1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235#if 0
236#define STB_TRUETYPE_IMPLEMENTATION
237#include "stb_truetype.h"
238
239unsigned char ttf_buffer[1<<20];
240unsigned char temp_bitmap[512*512];
241
242stbtt_bakedchar cdata[96];
243GLuint ftex;
244
245void my_stbtt_initfont(void)
246{
247 fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
248 stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata);
249
250 glGenTextures(1, &ftex);
251 glBindTexture(GL_TEXTURE_2D, ftex);
252 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
253
254 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
255}
256
257void my_stbtt_print(float x, float y, char *text)
258{
259
260 glEnable(GL_TEXTURE_2D);
261 glBindTexture(GL_TEXTURE_2D, ftex);
262 glBegin(GL_QUADS);
263 while (*text) {
264 if (*text >= 32 && *text < 128) {
265 stbtt_aligned_quad q;
266 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);
267 glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
268 glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
269 glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
270 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
271 }
272 ++text;
273 }
274 glEnd();
275}
276#endif
277
278
279
280
281
282
283#if 0
284#include <stdio.h>
285#define STB_TRUETYPE_IMPLEMENTATION
286#include "stb_truetype.h"
287
288char ttf_buffer[1<<25];
289
290int main(int argc, char **argv)
291{
292 stbtt_fontinfo font;
293 unsigned char *bitmap;
294 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
295
296 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
297
298 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
299 bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
300
301 for (j=0; j < h; ++j) {
302 for (i=0; i < w; ++i)
303 putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
304 putchar('\n');
305 }
306 return 0;
307}
308#endif
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327#if 0
328char buffer[24<<20];
329unsigned char screen[20][79];
330
331int main(int arg, char **argv)
332{
333 stbtt_fontinfo font;
334 int i,j,ascent,baseline,ch=0;
335 float scale, xpos=2;
336 char *text = "Heljo World!";
337
338 fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
339 stbtt_InitFont(&font, buffer, 0);
340
341 scale = stbtt_ScaleForPixelHeight(&font, 15);
342 stbtt_GetFontVMetrics(&font, &ascent,0,0);
343 baseline = (int) (ascent*scale);
344
345 while (text[ch]) {
346 int advance,lsb,x0,y0,x1,y1;
347 float x_shift = xpos - (float) floor(xpos);
348 stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
349 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
350 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
351
352
353
354
355 xpos += (advance * scale);
356 if (text[ch+1])
357 xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
358 ++ch;
359 }
360
361 for (j=0; j < 20; ++j) {
362 for (i=0; i < 78; ++i)
363 putchar(" .:ioVM@"[screen[j][i]>>5]);
364 putchar('\n');
365 }
366
367 return 0;
368}
369#endif
370
371
372
373
374
375
376
377
378
379
380#ifdef STB_TRUETYPE_IMPLEMENTATION
381
382 #ifndef stbtt_uint8
383 typedef unsigned char stbtt_uint8;
384 typedef signed char stbtt_int8;
385 typedef unsigned short stbtt_uint16;
386 typedef signed short stbtt_int16;
387 typedef unsigned int stbtt_uint32;
388 typedef signed int stbtt_int32;
389 #endif
390
391 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
392 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
393
394
395 #ifndef STBTT_ifloor
396 #include <math.h>
397 #define STBTT_ifloor(x) ((int) floor(x))
398 #define STBTT_iceil(x) ((int) ceil(x))
399 #endif
400
401 #ifndef STBTT_sqrt
402 #include <math.h>
403 #define STBTT_sqrt(x) sqrt(x)
404 #endif
405
406 #ifndef STBTT_fabs
407 #include <math.h>
408 #define STBTT_fabs(x) fabs(x)
409 #endif
410
411
412 #ifndef STBTT_malloc
413 #include <stdlib.h>
414 #define STBTT_malloc(x,u) ((void)(u),malloc(x))
415 #define STBTT_free(x,u) ((void)(u),free(x))
416 #endif
417
418 #ifndef STBTT_assert
419 #include <assert.h>
420 #define STBTT_assert(x) assert(x)
421 #endif
422
423 #ifndef STBTT_strlen
424 #include <string.h>
425 #define STBTT_strlen(x) strlen(x)
426 #endif
427
428 #ifndef STBTT_memcpy
429 #include <memory.h>
430 #define STBTT_memcpy memcpy
431 #define STBTT_memset memset
432 #endif
433#endif
434
435
436
437
438
439
440
441
442#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
443#define __STB_INCLUDE_STB_TRUETYPE_H__
444
445#ifdef STBTT_STATIC
446#define STBTT_DEF static
447#else
448#define STBTT_DEF extern
449#endif
450
451#ifdef __cplusplus
452extern "C" {
453#endif
454
455
456
457
458
459
460
461
462typedef struct
463{
464 unsigned short x0,y0,x1,y1;
465 float xoff,yoff,xadvance;
466} stbtt_bakedchar;
467
468STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
469 float pixel_height,
470 unsigned char *pixels, int pw, int ph,
471 int first_char, int num_chars,
472 stbtt_bakedchar *chardata);
473
474
475
476
477
478typedef struct
479{
480 float x0,y0,s0,t0;
481 float x1,y1,s1,t1;
482} stbtt_aligned_quad;
483
484STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph,
485 int char_index,
486 float *xpos, float *ypos,
487 stbtt_aligned_quad *q,
488 int opengl_fillrule);
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507typedef struct
508{
509 unsigned short x0,y0,x1,y1;
510 float xoff,yoff,xadvance;
511 float xoff2,yoff2;
512} stbtt_packedchar;
513
514typedef struct stbtt_pack_context stbtt_pack_context;
515typedef struct stbtt_fontinfo stbtt_fontinfo;
516#ifndef STB_RECT_PACK_VERSION
517typedef struct stbrp_rect stbrp_rect;
518#endif
519
520STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
521
522
523
524
525
526
527
528
529
530
531STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
532
533
534#define STBTT_POINT_SIZE(x) (-(x))
535
536STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
537 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
538
539
540
541
542
543
544
545
546
547
548
549
550
551typedef struct
552{
553 float font_size;
554 int first_unicode_codepoint_in_range;
555 int *array_of_unicode_codepoints;
556 int num_chars;
557 stbtt_packedchar *chardata_for_range;
558 unsigned char h_oversample, v_oversample;
559} stbtt_pack_range;
560
561STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
562
563
564
565
566
567STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph,
584 int char_index,
585 float *xpos, float *ypos,
586 stbtt_aligned_quad *q,
587 int align_to_integer);
588
589STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
590STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
591STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
592
593
594
595
596
597
598
599
600
601
602
603
604struct stbtt_pack_context {
605 void *user_allocator_context;
606 void *pack_info;
607 int width;
608 int height;
609 int stride_in_bytes;
610 int padding;
611 unsigned int h_oversample, v_oversample;
612 unsigned char *pixels;
613 void *nodes;
614};
615
616
617
618
619
620
621
622STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
623
624
625
626
627
628
629
630
631
632
633typedef struct stbtt_fontinfo
634{
635 void * userdata;
636 unsigned char * data;
637 int fontstart;
638
639 int numGlyphs;
640
641 int loca,head,glyf,hhea,hmtx,kern;
642 int index_map;
643 int indexToLocFormat;
644} stbtt_fontinfo;
645
646STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
647
648
649
650
651
652
653
654
655
656
657
658STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
659
660
661
662
663
664
665
666
667
668
669
670STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
671
672
673
674
675
676
677
678STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
679
680
681
682
683STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
684
685
686
687
688
689
690
691STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
692
693
694STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
695
696
697
698
699STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
700
701
702STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
703
704
705STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
706STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
707STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
708
709
710
711
712
713
714
715
716
717#ifndef STBTT_vmove
718 enum {
719 STBTT_vmove=1,
720 STBTT_vline,
721 STBTT_vcurve
722 };
723#endif
724
725#ifndef stbtt_vertex
726
727 #define stbtt_vertex_type short
728 typedef struct
729 {
730 stbtt_vertex_type x,y,cx,cy;
731 unsigned char type,padding;
732 } stbtt_vertex;
733#endif
734
735STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
736
737
738STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
739STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
740
741
742
743
744
745
746
747
748
749
750STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
751
752
753
754
755
756
757
758STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
759
760
761STBTT_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);
762
763
764
765
766
767
768
769
770STBTT_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);
771
772
773
774STBTT_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);
775
776
777
778
779
780STBTT_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);
781
782
783
784STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
785
786
787
788
789
790
791STBTT_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);
792
793
794
795
796
797STBTT_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);
798STBTT_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);
799STBTT_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);
800STBTT_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);
801STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
802STBTT_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);
803
804
805
806typedef struct
807{
808 int w,h,stride;
809 unsigned char *pixels;
810} stbtt__bitmap;
811
812
813STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result,
814 float flatness_in_pixels,
815 stbtt_vertex *vertices,
816 int num_verts,
817 float scale_x, float scale_y,
818 float shift_x, float shift_y,
819 int x_off, int y_off,
820 int invert,
821 void *userdata);
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
846
847
848
849
850#define STBTT_MACSTYLE_DONTCARE 0
851#define STBTT_MACSTYLE_BOLD 1
852#define STBTT_MACSTYLE_ITALIC 2
853#define STBTT_MACSTYLE_UNDERSCORE 4
854#define STBTT_MACSTYLE_NONE 8
855
856STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
857
858
859
860STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
861
862
863
864
865
866
867
868enum {
869 STBTT_PLATFORM_ID_UNICODE =0,
870 STBTT_PLATFORM_ID_MAC =1,
871 STBTT_PLATFORM_ID_ISO =2,
872 STBTT_PLATFORM_ID_MICROSOFT =3
873};
874
875enum {
876 STBTT_UNICODE_EID_UNICODE_1_0 =0,
877 STBTT_UNICODE_EID_UNICODE_1_1 =1,
878 STBTT_UNICODE_EID_ISO_10646 =2,
879 STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
880 STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
881};
882
883enum {
884 STBTT_MS_EID_SYMBOL =0,
885 STBTT_MS_EID_UNICODE_BMP =1,
886 STBTT_MS_EID_SHIFTJIS =2,
887 STBTT_MS_EID_UNICODE_FULL =10
888};
889
890enum {
891 STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
892 STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
893 STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
894 STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
895};
896
897enum {
898
899 STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
900 STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
901 STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
902 STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
903 STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
904 STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
905};
906
907enum {
908 STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
909 STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
910 STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
911 STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
912 STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
913 STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
914 STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
915};
916
917#ifdef __cplusplus
918}
919#endif
920
921#endif
922
923
924
925
926
927
928
929
930#ifdef STB_TRUETYPE_IMPLEMENTATION
931
932#ifndef STBTT_MAX_OVERSAMPLE
933#define STBTT_MAX_OVERSAMPLE 8
934#endif
935
936#if STBTT_MAX_OVERSAMPLE > 255
937#error "STBTT_MAX_OVERSAMPLE cannot be > 255"
938#endif
939
940typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
941
942#ifndef STBTT_RASTERIZER_VERSION
943#define STBTT_RASTERIZER_VERSION 2
944#endif
945
946
947
948
949
950
951
952
953
954#define ttBYTE(p) (* (stbtt_uint8 *) (p))
955#define ttCHAR(p) (* (stbtt_int8 *) (p))
956#define ttFixed(p) ttLONG(p)
957
958#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
959
960 #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
961 #define ttSHORT(p) (* (stbtt_int16 *) (p))
962 #define ttULONG(p) (* (stbtt_uint32 *) (p))
963 #define ttLONG(p) (* (stbtt_int32 *) (p))
964
965#else
966
967 static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
968 static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
969 static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
970 static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
971
972#endif
973
974#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
975#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
976
977static int stbtt__isfont(const stbtt_uint8 *font)
978{
979
980 if (stbtt_tag4(font, '1',0,0,0)) return 1;
981 if (stbtt_tag(font, "typ1")) return 1;
982 if (stbtt_tag(font, "OTTO")) return 1;
983 if (stbtt_tag4(font, 0,1,0,0)) return 1;
984 return 0;
985}
986
987
988static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
989{
990 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
991 stbtt_uint32 tabledir = fontstart + 12;
992 stbtt_int32 i;
993 for (i=0; i < num_tables; ++i) {
994 stbtt_uint32 loc = tabledir + 16*i;
995 if (stbtt_tag(data+loc+0, tag))
996 return ttULONG(data+loc+8);
997 }
998 return 0;
999}
1000
1001STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index)
1002{
1003
1004 if (stbtt__isfont(font_collection))
1005 return index == 0 ? 0 : -1;
1006
1007
1008 if (stbtt_tag(font_collection, "ttcf")) {
1009
1010 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1011 stbtt_int32 n = ttLONG(font_collection+8);
1012 if (index >= n)
1013 return -1;
1014 return ttULONG(font_collection+12+index*4);
1015 }
1016 }
1017 return -1;
1018}
1019
1020STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart)
1021{
1022 stbtt_uint8 *data = (stbtt_uint8 *) data2;
1023 stbtt_uint32 cmap, t;
1024 stbtt_int32 i,numTables;
1025
1026 info->data = data;
1027 info->fontstart = fontstart;
1028
1029 cmap = stbtt__find_table(data, fontstart, "cmap");
1030 info->loca = stbtt__find_table(data, fontstart, "loca");
1031 info->head = stbtt__find_table(data, fontstart, "head");
1032 info->glyf = stbtt__find_table(data, fontstart, "glyf");
1033 info->hhea = stbtt__find_table(data, fontstart, "hhea");
1034 info->hmtx = stbtt__find_table(data, fontstart, "hmtx");
1035 info->kern = stbtt__find_table(data, fontstart, "kern");
1036 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
1037 return 0;
1038
1039 t = stbtt__find_table(data, fontstart, "maxp");
1040 if (t)
1041 info->numGlyphs = ttUSHORT(data+t+4);
1042 else
1043 info->numGlyphs = 0xffff;
1044
1045
1046
1047
1048 numTables = ttUSHORT(data + cmap + 2);
1049 info->index_map = 0;
1050 for (i=0; i < numTables; ++i) {
1051 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1052
1053 switch(ttUSHORT(data+encoding_record)) {
1054 case STBTT_PLATFORM_ID_MICROSOFT:
1055 switch (ttUSHORT(data+encoding_record+2)) {
1056 case STBTT_MS_EID_UNICODE_BMP:
1057 case STBTT_MS_EID_UNICODE_FULL:
1058
1059 info->index_map = cmap + ttULONG(data+encoding_record+4);
1060 break;
1061 }
1062 break;
1063 case STBTT_PLATFORM_ID_UNICODE:
1064
1065
1066 info->index_map = cmap + ttULONG(data+encoding_record+4);
1067 break;
1068 }
1069 }
1070 if (info->index_map == 0)
1071 return 0;
1072
1073 info->indexToLocFormat = ttUSHORT(data+info->head + 50);
1074 return 1;
1075}
1076
1077STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
1078{
1079 stbtt_uint8 *data = info->data;
1080 stbtt_uint32 index_map = info->index_map;
1081
1082 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1083 if (format == 0) {
1084 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1085 if (unicode_codepoint < bytes-6)
1086 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1087 return 0;
1088 } else if (format == 6) {
1089 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1090 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1091 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1092 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1093 return 0;
1094 } else if (format == 2) {
1095 STBTT_assert(0);
1096 return 0;
1097 } else if (format == 4) {
1098 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1099 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1100 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1101 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1102
1103
1104 stbtt_uint32 endCount = index_map + 14;
1105 stbtt_uint32 search = endCount;
1106
1107 if (unicode_codepoint > 0xffff)
1108 return 0;
1109
1110
1111
1112 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1113 search += rangeShift*2;
1114
1115
1116 search -= 2;
1117 while (entrySelector) {
1118 stbtt_uint16 end;
1119 searchRange >>= 1;
1120 end = ttUSHORT(data + search + searchRange*2);
1121 if (unicode_codepoint > end)
1122 search += searchRange*2;
1123 --entrySelector;
1124 }
1125 search += 2;
1126
1127 {
1128 stbtt_uint16 offset, start;
1129 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
1130
1131 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1132 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1133 if (unicode_codepoint < start)
1134 return 0;
1135
1136 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1137 if (offset == 0)
1138 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1139
1140 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1141 }
1142 } else if (format == 12 || format == 13) {
1143 stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1144 stbtt_int32 low,high;
1145 low = 0; high = (stbtt_int32)ngroups;
1146
1147 while (low < high) {
1148 stbtt_int32 mid = low + ((high-low) >> 1);
1149 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1150 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1151 if ((stbtt_uint32) unicode_codepoint < start_char)
1152 high = mid;
1153 else if ((stbtt_uint32) unicode_codepoint > end_char)
1154 low = mid+1;
1155 else {
1156 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1157 if (format == 12)
1158 return start_glyph + unicode_codepoint-start_char;
1159 else
1160 return start_glyph;
1161 }
1162 }
1163 return 0;
1164 }
1165
1166 STBTT_assert(0);
1167 return 0;
1168}
1169
1170STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
1171{
1172 return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
1173}
1174
1175static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1176{
1177 v->type = type;
1178 v->x = (stbtt_int16) x;
1179 v->y = (stbtt_int16) y;
1180 v->cx = (stbtt_int16) cx;
1181 v->cy = (stbtt_int16) cy;
1182}
1183
1184static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
1185{
1186 int g1,g2;
1187
1188 if (glyph_index >= info->numGlyphs) return -1;
1189 if (info->indexToLocFormat >= 2) return -1;
1190
1191 if (info->indexToLocFormat == 0) {
1192 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
1193 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
1194 } else {
1195 g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
1196 g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
1197 }
1198
1199 return g1==g2 ? -1 : g1;
1200}
1201
1202STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
1203{
1204 int g = stbtt__GetGlyfOffset(info, glyph_index);
1205 if (g < 0) return 0;
1206
1207 if (x0) *x0 = ttSHORT(info->data + g + 2);
1208 if (y0) *y0 = ttSHORT(info->data + g + 4);
1209 if (x1) *x1 = ttSHORT(info->data + g + 6);
1210 if (y1) *y1 = ttSHORT(info->data + g + 8);
1211 return 1;
1212}
1213
1214STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
1215{
1216 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
1217}
1218
1219STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
1220{
1221 stbtt_int16 numberOfContours;
1222 int g = stbtt__GetGlyfOffset(info, glyph_index);
1223 if (g < 0) return 1;
1224 numberOfContours = ttSHORT(info->data + g);
1225 return numberOfContours == 0;
1226}
1227
1228static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
1229 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1230{
1231 if (start_off) {
1232 if (was_off)
1233 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1234 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
1235 } else {
1236 if (was_off)
1237 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
1238 else
1239 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
1240 }
1241 return num_vertices;
1242}
1243
1244STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
1245{
1246 stbtt_int16 numberOfContours;
1247 stbtt_uint8 *endPtsOfContours;
1248 stbtt_uint8 *data = info->data;
1249 stbtt_vertex *vertices=0;
1250 int num_vertices=0;
1251 int g = stbtt__GetGlyfOffset(info, glyph_index);
1252
1253 *pvertices = NULL;
1254
1255 if (g < 0) return 0;
1256
1257 numberOfContours = ttSHORT(data + g);
1258
1259 if (numberOfContours > 0) {
1260 stbtt_uint8 flags=0,flagcount;
1261 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1262 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1263 stbtt_uint8 *points;
1264 endPtsOfContours = (data + g + 10);
1265 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1266 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1267
1268 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1269
1270 m = n + 2*numberOfContours;
1271 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
1272 if (vertices == 0)
1273 return 0;
1274
1275 next_move = 0;
1276 flagcount=0;
1277
1278
1279
1280
1281
1282 off = m - n;
1283
1284
1285
1286 for (i=0; i < n; ++i) {
1287 if (flagcount == 0) {
1288 flags = *points++;
1289 if (flags & 8)
1290 flagcount = *points++;
1291 } else
1292 --flagcount;
1293 vertices[off+i].type = flags;
1294 }
1295
1296
1297 x=0;
1298 for (i=0; i < n; ++i) {
1299 flags = vertices[off+i].type;
1300 if (flags & 2) {
1301 stbtt_int16 dx = *points++;
1302 x += (flags & 16) ? dx : -dx;
1303 } else {
1304 if (!(flags & 16)) {
1305 x = x + (stbtt_int16) (points[0]*256 + points[1]);
1306 points += 2;
1307 }
1308 }
1309 vertices[off+i].x = (stbtt_int16) x;
1310 }
1311
1312
1313 y=0;
1314 for (i=0; i < n; ++i) {
1315 flags = vertices[off+i].type;
1316 if (flags & 4) {
1317 stbtt_int16 dy = *points++;
1318 y += (flags & 32) ? dy : -dy;
1319 } else {
1320 if (!(flags & 32)) {
1321 y = y + (stbtt_int16) (points[0]*256 + points[1]);
1322 points += 2;
1323 }
1324 }
1325 vertices[off+i].y = (stbtt_int16) y;
1326 }
1327
1328
1329 num_vertices=0;
1330 sx = sy = cx = cy = scx = scy = 0;
1331 for (i=0; i < n; ++i) {
1332 flags = vertices[off+i].type;
1333 x = (stbtt_int16) vertices[off+i].x;
1334 y = (stbtt_int16) vertices[off+i].y;
1335
1336 if (next_move == i) {
1337 if (i != 0)
1338 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1339
1340
1341 start_off = !(flags & 1);
1342 if (start_off) {
1343
1344
1345 scx = x;
1346 scy = y;
1347 if (!(vertices[off+i+1].type & 1)) {
1348
1349 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1350 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1351 } else {
1352
1353 sx = (stbtt_int32) vertices[off+i+1].x;
1354 sy = (stbtt_int32) vertices[off+i+1].y;
1355 ++i;
1356 }
1357 } else {
1358 sx = x;
1359 sy = y;
1360 }
1361 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
1362 was_off = 0;
1363 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1364 ++j;
1365 } else {
1366 if (!(flags & 1)) {
1367 if (was_off)
1368 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1369 cx = x;
1370 cy = y;
1371 was_off = 1;
1372 } else {
1373 if (was_off)
1374 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
1375 else
1376 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
1377 was_off = 0;
1378 }
1379 }
1380 }
1381 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1382 } else if (numberOfContours == -1) {
1383
1384 int more = 1;
1385 stbtt_uint8 *comp = data + g + 10;
1386 num_vertices = 0;
1387 vertices = 0;
1388 while (more) {
1389 stbtt_uint16 flags, gidx;
1390 int comp_num_verts = 0, i;
1391 stbtt_vertex *comp_verts = 0, *tmp = 0;
1392 float mtx[6] = {1,0,0,1,0,0}, m, n;
1393
1394 flags = ttSHORT(comp); comp+=2;
1395 gidx = ttSHORT(comp); comp+=2;
1396
1397 if (flags & 2) {
1398 if (flags & 1) {
1399 mtx[4] = ttSHORT(comp); comp+=2;
1400 mtx[5] = ttSHORT(comp); comp+=2;
1401 } else {
1402 mtx[4] = ttCHAR(comp); comp+=1;
1403 mtx[5] = ttCHAR(comp); comp+=1;
1404 }
1405 }
1406 else {
1407
1408 STBTT_assert(0);
1409 }
1410 if (flags & (1<<3)) {
1411 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1412 mtx[1] = mtx[2] = 0;
1413 } else if (flags & (1<<6)) {
1414 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1415 mtx[1] = mtx[2] = 0;
1416 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1417 } else if (flags & (1<<7)) {
1418 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1419 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1420 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1421 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1422 }
1423
1424
1425 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1426 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1427
1428
1429 comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
1430 if (comp_num_verts > 0) {
1431
1432 for (i = 0; i < comp_num_verts; ++i) {
1433 stbtt_vertex* v = &comp_verts[i];
1434 stbtt_vertex_type x,y;
1435 x=v->x; y=v->y;
1436 v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1437 v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1438 x=v->cx; y=v->cy;
1439 v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1440 v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1441 }
1442
1443 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
1444 if (!tmp) {
1445 if (vertices) STBTT_free(vertices, info->userdata);
1446 if (comp_verts) STBTT_free(comp_verts, info->userdata);
1447 return 0;
1448 }
1449 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
1450 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
1451 if (vertices) STBTT_free(vertices, info->userdata);
1452 vertices = tmp;
1453 STBTT_free(comp_verts, info->userdata);
1454 num_vertices += comp_num_verts;
1455 }
1456
1457 more = flags & (1<<5);
1458 }
1459 } else if (numberOfContours < 0) {
1460
1461 STBTT_assert(0);
1462 } else {
1463
1464 }
1465
1466 *pvertices = vertices;
1467 return num_vertices;
1468}
1469
1470STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
1471{
1472 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
1473 if (glyph_index < numOfLongHorMetrics) {
1474 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
1475 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
1476 } else {
1477 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
1478 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
1479 }
1480}
1481
1482STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
1483{
1484 stbtt_uint8 *data = info->data + info->kern;
1485 stbtt_uint32 needle, straw;
1486 int l, r, m;
1487
1488
1489 if (!info->kern)
1490 return 0;
1491 if (ttUSHORT(data+2) < 1)
1492 return 0;
1493 if (ttUSHORT(data+8) != 1)
1494 return 0;
1495
1496 l = 0;
1497 r = ttUSHORT(data+10) - 1;
1498 needle = glyph1 << 16 | glyph2;
1499 while (l <= r) {
1500 m = (l + r) >> 1;
1501 straw = ttULONG(data+18+(m*6));
1502 if (needle < straw)
1503 r = m - 1;
1504 else if (needle > straw)
1505 l = m + 1;
1506 else
1507 return ttSHORT(data+22+(m*6));
1508 }
1509 return 0;
1510}
1511
1512STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
1513{
1514 if (!info->kern)
1515 return 0;
1516 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
1517}
1518
1519STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
1520{
1521 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
1522}
1523
1524STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
1525{
1526 if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
1527 if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
1528 if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
1529}
1530
1531STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
1532{
1533 *x0 = ttSHORT(info->data + info->head + 36);
1534 *y0 = ttSHORT(info->data + info->head + 38);
1535 *x1 = ttSHORT(info->data + info->head + 40);
1536 *y1 = ttSHORT(info->data + info->head + 42);
1537}
1538
1539STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
1540{
1541 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
1542 return (float) height / fheight;
1543}
1544
1545STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
1546{
1547 int unitsPerEm = ttUSHORT(info->data + info->head + 18);
1548 return pixels / unitsPerEm;
1549}
1550
1551STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
1552{
1553 STBTT_free(v, info->userdata);
1554}
1555
1556
1557
1558
1559
1560
1561STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
1562{
1563 int x0,y0,x1,y1;
1564 if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
1565
1566 if (ix0) *ix0 = 0;
1567 if (iy0) *iy0 = 0;
1568 if (ix1) *ix1 = 0;
1569 if (iy1) *iy1 = 0;
1570 } else {
1571
1572 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
1573 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
1574 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
1575 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
1576 }
1577}
1578
1579STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
1580{
1581 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
1582}
1583
1584STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
1585{
1586 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
1587}
1588
1589STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
1590{
1591 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
1592}
1593
1594
1595
1596
1597
1598typedef struct stbtt__hheap_chunk
1599{
1600 struct stbtt__hheap_chunk *next;
1601} stbtt__hheap_chunk;
1602
1603typedef struct stbtt__hheap
1604{
1605 struct stbtt__hheap_chunk *head;
1606 void *first_free;
1607 int num_remaining_in_head_chunk;
1608} stbtt__hheap;
1609
1610static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
1611{
1612 if (hh->first_free) {
1613 void *p = hh->first_free;
1614 hh->first_free = * (void **) p;
1615 return p;
1616 } else {
1617 if (hh->num_remaining_in_head_chunk == 0) {
1618 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
1619 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
1620 if (c == NULL)
1621 return NULL;
1622 c->next = hh->head;
1623 hh->head = c;
1624 hh->num_remaining_in_head_chunk = count;
1625 }
1626 --hh->num_remaining_in_head_chunk;
1627 return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk;
1628 }
1629}
1630
1631static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
1632{
1633 *(void **) p = hh->first_free;
1634 hh->first_free = p;
1635}
1636
1637static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
1638{
1639 stbtt__hheap_chunk *c = hh->head;
1640 while (c) {
1641 stbtt__hheap_chunk *n = c->next;
1642 STBTT_free(c, userdata);
1643 c = n;
1644 }
1645}
1646
1647typedef struct stbtt__edge {
1648 float x0,y0, x1,y1;
1649 int invert;
1650} stbtt__edge;
1651
1652
1653typedef struct stbtt__active_edge
1654{
1655 struct stbtt__active_edge *next;
1656 #if STBTT_RASTERIZER_VERSION==1
1657 int x,dx;
1658 float ey;
1659 int direction;
1660 #elif STBTT_RASTERIZER_VERSION==2
1661 float fx,fdx,fdy;
1662 float direction;
1663 float sy;
1664 float ey;
1665 #else
1666 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
1667 #endif
1668} stbtt__active_edge;
1669
1670#if STBTT_RASTERIZER_VERSION == 1
1671#define STBTT_FIXSHIFT 10
1672#define STBTT_FIX (1 << STBTT_FIXSHIFT)
1673#define STBTT_FIXMASK (STBTT_FIX-1)
1674
1675static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
1676{
1677 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
1678 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
1679 if (!z) return z;
1680
1681
1682 if (dxdy < 0)
1683 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
1684 else
1685 z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
1686
1687 z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0));
1688 z->x -= off_x * STBTT_FIX;
1689
1690 z->ey = e->y1;
1691 z->next = 0;
1692 z->direction = e->invert ? 1 : -1;
1693 return z;
1694}
1695#elif STBTT_RASTERIZER_VERSION == 2
1696static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
1697{
1698 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
1699 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
1700
1701 if (!z) return z;
1702 z->fdx = dxdy;
1703 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
1704 z->fx = e->x0 + dxdy * (start_point - e->y0);
1705 z->fx -= off_x;
1706 z->direction = e->invert ? 1.0f : -1.0f;
1707 z->sy = e->y0;
1708 z->ey = e->y1;
1709 z->next = 0;
1710 return z;
1711}
1712#else
1713#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
1714#endif
1715
1716#if STBTT_RASTERIZER_VERSION == 1
1717
1718
1719
1720static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
1721{
1722
1723 int x0=0, w=0;
1724
1725 while (e) {
1726 if (w == 0) {
1727
1728 x0 = e->x; w += e->direction;
1729 } else {
1730 int x1 = e->x; w += e->direction;
1731
1732 if (w == 0) {
1733 int i = x0 >> STBTT_FIXSHIFT;
1734 int j = x1 >> STBTT_FIXSHIFT;
1735
1736 if (i < len && j >= 0) {
1737 if (i == j) {
1738
1739 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
1740 } else {
1741 if (i >= 0)
1742 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
1743 else
1744 i = -1;
1745
1746 if (j < len)
1747 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
1748 else
1749 j = len;
1750
1751 for (++i; i < j; ++i)
1752 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
1753 }
1754 }
1755 }
1756 }
1757
1758 e = e->next;
1759 }
1760}
1761
1762static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
1763{
1764 stbtt__hheap hh = { 0, 0, 0 };
1765 stbtt__active_edge *active = NULL;
1766 int y,j=0;
1767 int max_weight = (255 / vsubsample);
1768 int s;
1769 unsigned char scanline_data[512], *scanline;
1770
1771 if (result->w > 512)
1772 scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
1773 else
1774 scanline = scanline_data;
1775
1776 y = off_y * vsubsample;
1777 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
1778
1779 while (j < result->h) {
1780 STBTT_memset(scanline, 0, result->w);
1781 for (s=0; s < vsubsample; ++s) {
1782
1783 float scan_y = y + 0.5f;
1784 stbtt__active_edge **step = &active;
1785
1786
1787
1788 while (*step) {
1789 stbtt__active_edge * z = *step;
1790 if (z->ey <= scan_y) {
1791 *step = z->next;
1792 STBTT_assert(z->direction);
1793 z->direction = 0;
1794 stbtt__hheap_free(&hh, z);
1795 } else {
1796 z->x += z->dx;
1797 step = &((*step)->next);
1798 }
1799 }
1800
1801
1802 for(;;) {
1803 int changed=0;
1804 step = &active;
1805 while (*step && (*step)->next) {
1806 if ((*step)->x > (*step)->next->x) {
1807 stbtt__active_edge *t = *step;
1808 stbtt__active_edge *q = t->next;
1809
1810 t->next = q->next;
1811 q->next = t;
1812 *step = q;
1813 changed = 1;
1814 }
1815 step = &(*step)->next;
1816 }
1817 if (!changed) break;
1818 }
1819
1820
1821 while (e->y0 <= scan_y) {
1822 if (e->y1 > scan_y) {
1823 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
1824
1825 if (active == NULL)
1826 active = z;
1827 else if (z->x < active->x) {
1828
1829 z->next = active;
1830 active = z;
1831 } else {
1832
1833 stbtt__active_edge *p = active;
1834 while (p->next && p->next->x < z->x)
1835 p = p->next;
1836
1837 z->next = p->next;
1838 p->next = z;
1839 }
1840 }
1841 ++e;
1842 }
1843
1844
1845 if (active)
1846 stbtt__fill_active_edges(scanline, result->w, active, max_weight);
1847
1848 ++y;
1849 }
1850 STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
1851 ++j;
1852 }
1853
1854 stbtt__hheap_cleanup(&hh, userdata);
1855
1856 if (scanline != scanline_data)
1857 STBTT_free(scanline, userdata);
1858}
1859
1860#elif STBTT_RASTERIZER_VERSION == 2
1861
1862
1863
1864static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
1865{
1866 if (y0 == y1) return;
1867 STBTT_assert(y0 < y1);
1868 STBTT_assert(e->sy <= e->ey);
1869 if (y0 > e->ey) return;
1870 if (y1 < e->sy) return;
1871 if (y0 < e->sy) {
1872 x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
1873 y0 = e->sy;
1874 }
1875 if (y1 > e->ey) {
1876 x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
1877 y1 = e->ey;
1878 }
1879
1880 if (x0 == x)
1881 STBTT_assert(x1 <= x+1);
1882 else if (x0 == x+1)
1883 STBTT_assert(x1 >= x);
1884 else if (x0 <= x)
1885 STBTT_assert(x1 <= x);
1886 else if (x0 >= x+1)
1887 STBTT_assert(x1 >= x+1);
1888 else
1889 STBTT_assert(x1 >= x && x1 <= x+1);
1890
1891 if (x0 <= x && x1 <= x)
1892 scanline[x] += e->direction * (y1-y0);
1893 else if (x0 >= x+1 && x1 >= x+1)
1894 ;
1895 else {
1896 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
1897 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2);
1898 }
1899}
1900
1901static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
1902{
1903 float y_bottom = y_top+1;
1904
1905 while (e) {
1906
1907
1908
1909 STBTT_assert(e->ey >= y_top);
1910
1911 if (e->fdx == 0) {
1912 float x0 = e->fx;
1913 if (x0 < len) {
1914 if (x0 >= 0) {
1915 stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
1916 stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
1917 } else {
1918 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
1919 }
1920 }
1921 } else {
1922 float x0 = e->fx;
1923 float dx = e->fdx;
1924 float xb = x0 + dx;
1925 float x_top, x_bottom;
1926 float sy0,sy1;
1927 float dy = e->fdy;
1928 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
1929
1930
1931
1932
1933 if (e->sy > y_top) {
1934 x_top = x0 + dx * (e->sy - y_top);
1935 sy0 = e->sy;
1936 } else {
1937 x_top = x0;
1938 sy0 = y_top;
1939 }
1940 if (e->ey < y_bottom) {
1941 x_bottom = x0 + dx * (e->ey - y_top);
1942 sy1 = e->ey;
1943 } else {
1944 x_bottom = xb;
1945 sy1 = y_bottom;
1946 }
1947
1948 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
1949
1950
1951 if ((int) x_top == (int) x_bottom) {
1952 float height;
1953
1954 int x = (int) x_top;
1955 height = sy1 - sy0;
1956 STBTT_assert(x >= 0 && x < len);
1957 scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
1958 scanline_fill[x] += e->direction * height;
1959 } else {
1960 int x,x1,x2;
1961 float y_crossing, step, sign, area;
1962
1963 if (x_top > x_bottom) {
1964
1965 float t;
1966 sy0 = y_bottom - (sy0 - y_top);
1967 sy1 = y_bottom - (sy1 - y_top);
1968 t = sy0, sy0 = sy1, sy1 = t;
1969 t = x_bottom, x_bottom = x_top, x_top = t;
1970 dx = -dx;
1971 dy = -dy;
1972 t = x0, x0 = xb, xb = t;
1973 }
1974
1975 x1 = (int) x_top;
1976 x2 = (int) x_bottom;
1977
1978 y_crossing = (x1+1 - x0) * dy + y_top;
1979
1980 sign = e->direction;
1981
1982 area = sign * (y_crossing-sy0);
1983
1984 scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
1985
1986 step = sign * dy;
1987 for (x = x1+1; x < x2; ++x) {
1988 scanline[x] += area + step/2;
1989 area += step;
1990 }
1991 y_crossing += dy * (x2 - (x1+1));
1992
1993 STBTT_assert(fabs(area) <= 1.01f);
1994
1995 scanline[x2] += area + sign * (1-(x_bottom-x2)/2) * (sy1-y_crossing);
1996
1997 scanline_fill[x2] += sign * (sy1-sy0);
1998 }
1999 } else {
2000
2001
2002
2003
2004 int x;
2005 for (x=0; x < len; ++x) {
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020 float y0 = y_top;
2021 float x1 = (float) (x);
2022 float x2 = (float) (x+1);
2023 float x3 = xb;
2024 float y3 = y_bottom;
2025 float y1,y2;
2026
2027
2028
2029
2030 y1 = (x - x0) / dx + y_top;
2031 y2 = (x+1 - x0) / dx + y_top;
2032
2033 if (x0 < x1 && x3 > x2) {
2034 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
2035 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
2036 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
2037 } else if (x3 < x1 && x0 > x2) {
2038 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
2039 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
2040 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
2041 } else if (x0 < x1 && x3 > x1) {
2042 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
2043 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
2044 } else if (x3 < x1 && x0 > x1) {
2045 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
2046 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
2047 } else if (x0 < x2 && x3 > x2) {
2048 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
2049 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
2050 } else if (x3 < x2 && x0 > x2) {
2051 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
2052 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
2053 } else {
2054 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
2055 }
2056 }
2057 }
2058 }
2059 e = e->next;
2060 }
2061}
2062
2063
2064static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
2065{
2066 stbtt__hheap hh = { 0, 0, 0 };
2067 stbtt__active_edge *active = NULL;
2068 int y,j=0, i;
2069 float scanline_data[129], *scanline, *scanline2;
2070
2071 if (result->w > 64)
2072 scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
2073 else
2074 scanline = scanline_data;
2075
2076 scanline2 = scanline + result->w;
2077
2078 y = off_y;
2079 e[n].y0 = (float) (off_y + result->h) + 1;
2080
2081 while (j < result->h) {
2082
2083 float scan_y_top = y + 0.0f;
2084 float scan_y_bottom = y + 1.0f;
2085 stbtt__active_edge **step = &active;
2086
2087 STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
2088 STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
2089
2090
2091
2092 while (*step) {
2093 stbtt__active_edge * z = *step;
2094 if (z->ey <= scan_y_top) {
2095 *step = z->next;
2096 STBTT_assert(z->direction);
2097 z->direction = 0;
2098 stbtt__hheap_free(&hh, z);
2099 } else {
2100 step = &((*step)->next);
2101 }
2102 }
2103
2104
2105 while (e->y0 <= scan_y_bottom) {
2106 if (e->y0 != e->y1) {
2107 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
2108 STBTT_assert(z->ey >= scan_y_top);
2109
2110 z->next = active;
2111 active = z;
2112 }
2113 ++e;
2114 }
2115
2116
2117 if (active)
2118 stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
2119
2120 {
2121 float sum = 0;
2122 for (i=0; i < result->w; ++i) {
2123 float k;
2124 int m;
2125 sum += scanline2[i];
2126 k = scanline[i] + sum;
2127 k = (float) STBTT_fabs(k)*255 + 0.5f;
2128 m = (int) k;
2129 if (m > 255) m = 255;
2130 result->pixels[j*result->stride + i] = (unsigned char) m;
2131 }
2132 }
2133
2134 step = &active;
2135 while (*step) {
2136 stbtt__active_edge *z = *step;
2137 z->fx += z->fdx;
2138 step = &((*step)->next);
2139 }
2140
2141 ++y;
2142 ++j;
2143 }
2144
2145 stbtt__hheap_cleanup(&hh, userdata);
2146
2147 if (scanline != scanline_data)
2148 STBTT_free(scanline, userdata);
2149}
2150#else
2151#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2152#endif
2153
2154#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
2155
2156static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
2157{
2158 int i,j;
2159 for (i=1; i < n; ++i) {
2160 stbtt__edge t = p[i], *a = &t;
2161 j = i;
2162 while (j > 0) {
2163 stbtt__edge *b = &p[j-1];
2164 int c = STBTT__COMPARE(a,b);
2165 if (!c) break;
2166 p[j] = p[j-1];
2167 --j;
2168 }
2169 if (i != j)
2170 p[j] = t;
2171 }
2172}
2173
2174static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
2175{
2176
2177 while (n > 12) {
2178 stbtt__edge t;
2179 int c01,c12,c,m,i,j;
2180
2181
2182 m = n >> 1;
2183 c01 = STBTT__COMPARE(&p[0],&p[m]);
2184 c12 = STBTT__COMPARE(&p[m],&p[n-1]);
2185
2186 if (c01 != c12) {
2187
2188 int z;
2189 c = STBTT__COMPARE(&p[0],&p[n-1]);
2190
2191
2192 z = (c == c12) ? 0 : n-1;
2193 t = p[z];
2194 p[z] = p[m];
2195 p[m] = t;
2196 }
2197
2198
2199 t = p[0];
2200 p[0] = p[m];
2201 p[m] = t;
2202
2203
2204 i=1;
2205 j=n-1;
2206 for(;;) {
2207
2208
2209 for (;;++i) {
2210 if (!STBTT__COMPARE(&p[i], &p[0])) break;
2211 }
2212 for (;;--j) {
2213 if (!STBTT__COMPARE(&p[0], &p[j])) break;
2214 }
2215
2216 if (i >= j) break;
2217 t = p[i];
2218 p[i] = p[j];
2219 p[j] = t;
2220
2221 ++i;
2222 --j;
2223 }
2224
2225 if (j < (n-i)) {
2226 stbtt__sort_edges_quicksort(p,j);
2227 p = p+i;
2228 n = n-i;
2229 } else {
2230 stbtt__sort_edges_quicksort(p+i, n-i);
2231 n = j;
2232 }
2233 }
2234}
2235
2236static void stbtt__sort_edges(stbtt__edge *p, int n)
2237{
2238 stbtt__sort_edges_quicksort(p, n);
2239 stbtt__sort_edges_ins_sort(p, n);
2240}
2241
2242typedef struct
2243{
2244 float x,y;
2245} stbtt__point;
2246
2247static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
2248{
2249 float y_scale_inv = invert ? -scale_y : scale_y;
2250 stbtt__edge *e;
2251 int n,i,j,k,m;
2252#if STBTT_RASTERIZER_VERSION == 1
2253 int vsubsample = result->h < 8 ? 15 : 5;
2254#elif STBTT_RASTERIZER_VERSION == 2
2255 int vsubsample = 1;
2256#else
2257 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2258#endif
2259
2260
2261
2262 n = 0;
2263 for (i=0; i < windings; ++i)
2264 n += wcount[i];
2265
2266 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata);
2267 if (e == 0) return;
2268 n = 0;
2269
2270 m=0;
2271 for (i=0; i < windings; ++i) {
2272 stbtt__point *p = pts + m;
2273 m += wcount[i];
2274 j = wcount[i]-1;
2275 for (k=0; k < wcount[i]; j=k++) {
2276 int a=k,b=j;
2277
2278 if (p[j].y == p[k].y)
2279 continue;
2280
2281 e[n].invert = 0;
2282 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
2283 e[n].invert = 1;
2284 a=j,b=k;
2285 }
2286 e[n].x0 = p[a].x * scale_x + shift_x;
2287 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
2288 e[n].x1 = p[b].x * scale_x + shift_x;
2289 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
2290 ++n;
2291 }
2292 }
2293
2294
2295
2296 stbtt__sort_edges(e, n);
2297
2298
2299 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
2300
2301 STBTT_free(e, userdata);
2302}
2303
2304static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
2305{
2306 if (!points) return;
2307 points[n].x = x;
2308 points[n].y = y;
2309}
2310
2311
2312static 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)
2313{
2314
2315 float mx = (x0 + 2*x1 + x2)/4;
2316 float my = (y0 + 2*y1 + y2)/4;
2317
2318 float dx = (x0+x2)/2 - mx;
2319 float dy = (y0+y2)/2 - my;
2320 if (n > 16)
2321 return 1;
2322 if (dx*dx+dy*dy > objspace_flatness_squared) {
2323 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
2324 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
2325 } else {
2326 stbtt__add_point(points, *num_points,x2,y2);
2327 *num_points = *num_points+1;
2328 }
2329 return 1;
2330}
2331
2332
2333static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
2334{
2335 stbtt__point *points=0;
2336 int num_points=0;
2337
2338 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
2339 int i,n=0,start=0, pass;
2340
2341
2342 for (i=0; i < num_verts; ++i)
2343 if (vertices[i].type == STBTT_vmove)
2344 ++n;
2345
2346 *num_contours = n;
2347 if (n == 0) return 0;
2348
2349 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
2350
2351 if (*contour_lengths == 0) {
2352 *num_contours = 0;
2353 return 0;
2354 }
2355
2356
2357 for (pass=0; pass < 2; ++pass) {
2358 float x=0,y=0;
2359 if (pass == 1) {
2360 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
2361 if (points == NULL) goto error;
2362 }
2363 num_points = 0;
2364 n= -1;
2365 for (i=0; i < num_verts; ++i) {
2366 switch (vertices[i].type) {
2367 case STBTT_vmove:
2368
2369 if (n >= 0)
2370 (*contour_lengths)[n] = num_points - start;
2371 ++n;
2372 start = num_points;
2373
2374 x = vertices[i].x, y = vertices[i].y;
2375 stbtt__add_point(points, num_points++, x,y);
2376 break;
2377 case STBTT_vline:
2378 x = vertices[i].x, y = vertices[i].y;
2379 stbtt__add_point(points, num_points++, x, y);
2380 break;
2381 case STBTT_vcurve:
2382 stbtt__tesselate_curve(points, &num_points, x,y,
2383 vertices[i].cx, vertices[i].cy,
2384 vertices[i].x, vertices[i].y,
2385 objspace_flatness_squared, 0);
2386 x = vertices[i].x, y = vertices[i].y;
2387 break;
2388 }
2389 }
2390 (*contour_lengths)[n] = num_points - start;
2391 }
2392
2393 return points;
2394error:
2395 STBTT_free(points, userdata);
2396 STBTT_free(*contour_lengths, userdata);
2397 *contour_lengths = 0;
2398 *num_contours = 0;
2399 return NULL;
2400}
2401
2402STBTT_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)
2403{
2404 float scale = scale_x > scale_y ? scale_y : scale_x;
2405 int winding_count, *winding_lengths;
2406 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
2407 if (windings) {
2408 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
2409 STBTT_free(winding_lengths, userdata);
2410 STBTT_free(windings, userdata);
2411 }
2412}
2413
2414STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
2415{
2416 STBTT_free(bitmap, userdata);
2417}
2418
2419STBTT_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)
2420{
2421 int ix0,iy0,ix1,iy1;
2422 stbtt__bitmap gbm;
2423 stbtt_vertex *vertices;
2424 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
2425
2426 if (scale_x == 0) scale_x = scale_y;
2427 if (scale_y == 0) {
2428 if (scale_x == 0) {
2429 STBTT_free(vertices, info->userdata);
2430 return NULL;
2431 }
2432 scale_y = scale_x;
2433 }
2434
2435 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
2436
2437
2438 gbm.w = (ix1 - ix0);
2439 gbm.h = (iy1 - iy0);
2440 gbm.pixels = NULL;
2441
2442 if (width ) *width = gbm.w;
2443 if (height) *height = gbm.h;
2444 if (xoff ) *xoff = ix0;
2445 if (yoff ) *yoff = iy0;
2446
2447 if (gbm.w && gbm.h) {
2448 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
2449 if (gbm.pixels) {
2450 gbm.stride = gbm.w;
2451
2452 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
2453 }
2454 }
2455 STBTT_free(vertices, info->userdata);
2456 return gbm.pixels;
2457}
2458
2459STBTT_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)
2460{
2461 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
2462}
2463
2464STBTT_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)
2465{
2466 int ix0,iy0;
2467 stbtt_vertex *vertices;
2468 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
2469 stbtt__bitmap gbm;
2470
2471 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
2472 gbm.pixels = output;
2473 gbm.w = out_w;
2474 gbm.h = out_h;
2475 gbm.stride = out_stride;
2476
2477 if (gbm.w && gbm.h)
2478 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
2479
2480 STBTT_free(vertices, info->userdata);
2481}
2482
2483STBTT_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)
2484{
2485 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
2486}
2487
2488STBTT_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)
2489{
2490 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
2491}
2492
2493STBTT_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)
2494{
2495 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
2496}
2497
2498STBTT_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)
2499{
2500 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
2501}
2502
2503STBTT_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)
2504{
2505 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
2506}
2507
2508
2509
2510
2511
2512
2513
2514STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
2515 float pixel_height,
2516 unsigned char *pixels, int pw, int ph,
2517 int first_char, int num_chars,
2518 stbtt_bakedchar *chardata)
2519{
2520 float scale;
2521 int x,y,bottom_y, i;
2522 stbtt_fontinfo f;
2523 if (!stbtt_InitFont(&f, data, offset))
2524 return -1;
2525 STBTT_memset(pixels, 0, pw*ph);
2526 x=y=1;
2527 bottom_y = 1;
2528
2529 scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
2530
2531 for (i=0; i < num_chars; ++i) {
2532 int advance, lsb, x0,y0,x1,y1,gw,gh;
2533 int g = stbtt_FindGlyphIndex(&f, first_char + i);
2534 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
2535 stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
2536 gw = x1-x0;
2537 gh = y1-y0;
2538 if (x + gw + 1 >= pw)
2539 y = bottom_y, x = 1;
2540 if (y + gh + 1 >= ph)
2541 return -i;
2542 STBTT_assert(x+gw < pw);
2543 STBTT_assert(y+gh < ph);
2544 stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
2545 chardata[i].x0 = (stbtt_int16) x;
2546 chardata[i].y0 = (stbtt_int16) y;
2547 chardata[i].x1 = (stbtt_int16) (x + gw);
2548 chardata[i].y1 = (stbtt_int16) (y + gh);
2549 chardata[i].xadvance = scale * advance;
2550 chardata[i].xoff = (float) x0;
2551 chardata[i].yoff = (float) y0;
2552 x = x + gw + 1;
2553 if (y+gh+1 > bottom_y)
2554 bottom_y = y+gh+1;
2555 }
2556 return bottom_y;
2557}
2558
2559STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
2560{
2561 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
2562 float ipw = 1.0f / pw, iph = 1.0f / ph;
2563 stbtt_bakedchar *b = chardata + char_index;
2564 int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
2565 int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
2566
2567 q->x0 = round_x + d3d_bias;
2568 q->y0 = round_y + d3d_bias;
2569 q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
2570 q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
2571
2572 q->s0 = b->x0 * ipw;
2573 q->t0 = b->y0 * iph;
2574 q->s1 = b->x1 * ipw;
2575 q->t1 = b->y1 * iph;
2576
2577 *xpos += b->xadvance;
2578}
2579
2580
2581
2582
2583
2584
2585#ifndef STB_RECT_PACK_VERSION
2586#ifdef _MSC_VER
2587#define STBTT__NOTUSED(v) (void)(v)
2588#else
2589#define STBTT__NOTUSED(v) (void)sizeof(v)
2590#endif
2591
2592typedef int stbrp_coord;
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605typedef struct
2606{
2607 int width,height;
2608 int x,y,bottom_y;
2609} stbrp_context;
2610
2611typedef struct
2612{
2613 unsigned char x;
2614} stbrp_node;
2615
2616struct stbrp_rect
2617{
2618 stbrp_coord x,y;
2619 int id,w,h,was_packed;
2620};
2621
2622static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
2623{
2624 con->width = pw;
2625 con->height = ph;
2626 con->x = 0;
2627 con->y = 0;
2628 con->bottom_y = 0;
2629 STBTT__NOTUSED(nodes);
2630 STBTT__NOTUSED(num_nodes);
2631}
2632
2633static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
2634{
2635 int i;
2636 for (i=0; i < num_rects; ++i) {
2637 if (con->x + rects[i].w > con->width) {
2638 con->x = 0;
2639 con->y = con->bottom_y;
2640 }
2641 if (con->y + rects[i].h > con->height)
2642 break;
2643 rects[i].x = con->x;
2644 rects[i].y = con->y;
2645 rects[i].was_packed = 1;
2646 con->x += rects[i].w;
2647 if (con->y + rects[i].h > con->bottom_y)
2648 con->bottom_y = con->y + rects[i].h;
2649 }
2650 for ( ; i < num_rects; ++i)
2651 rects[i].was_packed = 0;
2652}
2653#endif
2654
2655
2656
2657
2658
2659
2660
2661
2662STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
2663{
2664 stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
2665 int num_nodes = pw - padding;
2666 stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
2667
2668 if (context == NULL || nodes == NULL) {
2669 if (context != NULL) STBTT_free(context, alloc_context);
2670 if (nodes != NULL) STBTT_free(nodes , alloc_context);
2671 return 0;
2672 }
2673
2674 spc->user_allocator_context = alloc_context;
2675 spc->width = pw;
2676 spc->height = ph;
2677 spc->pixels = pixels;
2678 spc->pack_info = context;
2679 spc->nodes = nodes;
2680 spc->padding = padding;
2681 spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
2682 spc->h_oversample = 1;
2683 spc->v_oversample = 1;
2684
2685 stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
2686
2687 if (pixels)
2688 STBTT_memset(pixels, 0, pw*ph);
2689
2690 return 1;
2691}
2692
2693STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
2694{
2695 STBTT_free(spc->nodes , spc->user_allocator_context);
2696 STBTT_free(spc->pack_info, spc->user_allocator_context);
2697}
2698
2699STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
2700{
2701 STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
2702 STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
2703 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
2704 spc->h_oversample = h_oversample;
2705 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
2706 spc->v_oversample = v_oversample;
2707}
2708
2709#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
2710
2711static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
2712{
2713 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2714 int safe_w = w - kernel_width;
2715 int j;
2716 for (j=0; j < h; ++j) {
2717 int i;
2718 unsigned int total;
2719 STBTT_memset(buffer, 0, kernel_width);
2720
2721 total = 0;
2722
2723
2724 switch (kernel_width) {
2725 case 2:
2726 for (i=0; i <= safe_w; ++i) {
2727 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2728 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2729 pixels[i] = (unsigned char) (total / 2);
2730 }
2731 break;
2732 case 3:
2733 for (i=0; i <= safe_w; ++i) {
2734 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2735 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2736 pixels[i] = (unsigned char) (total / 3);
2737 }
2738 break;
2739 case 4:
2740 for (i=0; i <= safe_w; ++i) {
2741 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2742 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2743 pixels[i] = (unsigned char) (total / 4);
2744 }
2745 break;
2746 case 5:
2747 for (i=0; i <= safe_w; ++i) {
2748 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2749 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2750 pixels[i] = (unsigned char) (total / 5);
2751 }
2752 break;
2753 default:
2754 for (i=0; i <= safe_w; ++i) {
2755 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2756 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2757 pixels[i] = (unsigned char) (total / kernel_width);
2758 }
2759 break;
2760 }
2761
2762 for (; i < w; ++i) {
2763 STBTT_assert(pixels[i] == 0);
2764 total -= buffer[i & STBTT__OVER_MASK];
2765 pixels[i] = (unsigned char) (total / kernel_width);
2766 }
2767
2768 pixels += stride_in_bytes;
2769 }
2770}
2771
2772static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
2773{
2774 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2775 int safe_h = h - kernel_width;
2776 int j;
2777 for (j=0; j < w; ++j) {
2778 int i;
2779 unsigned int total;
2780 STBTT_memset(buffer, 0, kernel_width);
2781
2782 total = 0;
2783
2784
2785 switch (kernel_width) {
2786 case 2:
2787 for (i=0; i <= safe_h; ++i) {
2788 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2789 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2790 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
2791 }
2792 break;
2793 case 3:
2794 for (i=0; i <= safe_h; ++i) {
2795 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2796 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2797 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
2798 }
2799 break;
2800 case 4:
2801 for (i=0; i <= safe_h; ++i) {
2802 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2803 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2804 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
2805 }
2806 break;
2807 case 5:
2808 for (i=0; i <= safe_h; ++i) {
2809 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2810 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2811 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
2812 }
2813 break;
2814 default:
2815 for (i=0; i <= safe_h; ++i) {
2816 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2817 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2818 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
2819 }
2820 break;
2821 }
2822
2823 for (; i < h; ++i) {
2824 STBTT_assert(pixels[i*stride_in_bytes] == 0);
2825 total -= buffer[i & STBTT__OVER_MASK];
2826 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
2827 }
2828
2829 pixels += 1;
2830 }
2831}
2832
2833static float stbtt__oversample_shift(int oversample)
2834{
2835 if (!oversample)
2836 return 0.0f;
2837
2838
2839
2840
2841
2842 return (float)-(oversample - 1) / (2.0f * (float)oversample);
2843}
2844
2845
2846STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
2847{
2848 int i,j,k;
2849
2850 k=0;
2851 for (i=0; i < num_ranges; ++i) {
2852 float fh = ranges[i].font_size;
2853 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
2854 ranges[i].h_oversample = (unsigned char) spc->h_oversample;
2855 ranges[i].v_oversample = (unsigned char) spc->v_oversample;
2856 for (j=0; j < ranges[i].num_chars; ++j) {
2857 int x0,y0,x1,y1;
2858 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
2859 int glyph = stbtt_FindGlyphIndex(info, codepoint);
2860 stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
2861 scale * spc->h_oversample,
2862 scale * spc->v_oversample,
2863 0,0,
2864 &x0,&y0,&x1,&y1);
2865 rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
2866 rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
2867 ++k;
2868 }
2869 }
2870
2871 return k;
2872}
2873
2874
2875STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
2876{
2877 int i,j,k, return_value = 1;
2878
2879
2880 int old_h_over = spc->h_oversample;
2881 int old_v_over = spc->v_oversample;
2882
2883 k = 0;
2884 for (i=0; i < num_ranges; ++i) {
2885 float fh = ranges[i].font_size;
2886 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
2887 float recip_h,recip_v,sub_x,sub_y;
2888 spc->h_oversample = ranges[i].h_oversample;
2889 spc->v_oversample = ranges[i].v_oversample;
2890 recip_h = 1.0f / spc->h_oversample;
2891 recip_v = 1.0f / spc->v_oversample;
2892 sub_x = stbtt__oversample_shift(spc->h_oversample);
2893 sub_y = stbtt__oversample_shift(spc->v_oversample);
2894 for (j=0; j < ranges[i].num_chars; ++j) {
2895 stbrp_rect *r = &rects[k];
2896 if (r->was_packed) {
2897 stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
2898 int advance, lsb, x0,y0,x1,y1;
2899 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
2900 int glyph = stbtt_FindGlyphIndex(info, codepoint);
2901 stbrp_coord pad = (stbrp_coord) spc->padding;
2902
2903
2904 r->x += pad;
2905 r->y += pad;
2906 r->w -= pad;
2907 r->h -= pad;
2908 stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
2909 stbtt_GetGlyphBitmapBox(info, glyph,
2910 scale * spc->h_oversample,
2911 scale * spc->v_oversample,
2912 &x0,&y0,&x1,&y1);
2913 stbtt_MakeGlyphBitmapSubpixel(info,
2914 spc->pixels + r->x + r->y*spc->stride_in_bytes,
2915 r->w - spc->h_oversample+1,
2916 r->h - spc->v_oversample+1,
2917 spc->stride_in_bytes,
2918 scale * spc->h_oversample,
2919 scale * spc->v_oversample,
2920 0,0,
2921 glyph);
2922
2923 if (spc->h_oversample > 1)
2924 stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
2925 r->w, r->h, spc->stride_in_bytes,
2926 spc->h_oversample);
2927
2928 if (spc->v_oversample > 1)
2929 stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
2930 r->w, r->h, spc->stride_in_bytes,
2931 spc->v_oversample);
2932
2933 bc->x0 = (stbtt_int16) r->x;
2934 bc->y0 = (stbtt_int16) r->y;
2935 bc->x1 = (stbtt_int16) (r->x + r->w);
2936 bc->y1 = (stbtt_int16) (r->y + r->h);
2937 bc->xadvance = scale * advance;
2938 bc->xoff = (float) x0 * recip_h + sub_x;
2939 bc->yoff = (float) y0 * recip_v + sub_y;
2940 bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
2941 bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
2942 } else {
2943 return_value = 0;
2944 }
2945
2946 ++k;
2947 }
2948 }
2949
2950
2951 spc->h_oversample = old_h_over;
2952 spc->v_oversample = old_v_over;
2953
2954 return return_value;
2955}
2956
2957STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
2958{
2959 stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
2960}
2961
2962STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
2963{
2964 stbtt_fontinfo info;
2965 int i,j,n, return_value = 1;
2966
2967 stbrp_rect *rects;
2968
2969
2970 for (i=0; i < num_ranges; ++i)
2971 for (j=0; j < ranges[i].num_chars; ++j)
2972 ranges[i].chardata_for_range[j].x0 =
2973 ranges[i].chardata_for_range[j].y0 =
2974 ranges[i].chardata_for_range[j].x1 =
2975 ranges[i].chardata_for_range[j].y1 = 0;
2976
2977 n = 0;
2978 for (i=0; i < num_ranges; ++i)
2979 n += ranges[i].num_chars;
2980
2981 rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
2982 if (rects == NULL)
2983 return 0;
2984
2985 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
2986
2987 n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
2988
2989 stbtt_PackFontRangesPackRects(spc, rects, n);
2990
2991 return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
2992
2993 STBTT_free(rects, spc->user_allocator_context);
2994 return return_value;
2995}
2996
2997STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
2998 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
2999{
3000 stbtt_pack_range range;
3001 range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
3002 range.array_of_unicode_codepoints = NULL;
3003 range.num_chars = num_chars_in_range;
3004 range.chardata_for_range = chardata_for_range;
3005 range.font_size = font_size;
3006 return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
3007}
3008
3009STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
3010{
3011 float ipw = 1.0f / pw, iph = 1.0f / ph;
3012 stbtt_packedchar *b = chardata + char_index;
3013
3014 if (align_to_integer) {
3015 float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
3016 float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
3017 q->x0 = x;
3018 q->y0 = y;
3019 q->x1 = x + b->xoff2 - b->xoff;
3020 q->y1 = y + b->yoff2 - b->yoff;
3021 } else {
3022 q->x0 = *xpos + b->xoff;
3023 q->y0 = *ypos + b->yoff;
3024 q->x1 = *xpos + b->xoff2;
3025 q->y1 = *ypos + b->yoff2;
3026 }
3027
3028 q->s0 = b->x0 * ipw;
3029 q->t0 = b->y0 * iph;
3030 q->s1 = b->x1 * ipw;
3031 q->t1 = b->y1 * iph;
3032
3033 *xpos += b->xadvance;
3034}
3035
3036
3037
3038
3039
3040
3041
3042
3043static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2)
3044{
3045 stbtt_int32 i=0;
3046
3047
3048 while (len2) {
3049 stbtt_uint16 ch = s2[0]*256 + s2[1];
3050 if (ch < 0x80) {
3051 if (i >= len1) return -1;
3052 if (s1[i++] != ch) return -1;
3053 } else if (ch < 0x800) {
3054 if (i+1 >= len1) return -1;
3055 if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
3056 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
3057 } else if (ch >= 0xd800 && ch < 0xdc00) {
3058 stbtt_uint32 c;
3059 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
3060 if (i+3 >= len1) return -1;
3061 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
3062 if (s1[i++] != 0xf0 + (c >> 18)) return -1;
3063 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
3064 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
3065 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
3066 s2 += 2;
3067 len2 -= 2;
3068 } else if (ch >= 0xdc00 && ch < 0xe000) {
3069 return -1;
3070 } else {
3071 if (i+2 >= len1) return -1;
3072 if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
3073 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
3074 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
3075 }
3076 s2 += 2;
3077 len2 -= 2;
3078 }
3079 return i;
3080}
3081
3082STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
3083{
3084 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2);
3085}
3086
3087
3088
3089STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
3090{
3091 stbtt_int32 i,count,stringOffset;
3092 stbtt_uint8 *fc = font->data;
3093 stbtt_uint32 offset = font->fontstart;
3094 stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
3095 if (!nm) return NULL;
3096
3097 count = ttUSHORT(fc+nm+2);
3098 stringOffset = nm + ttUSHORT(fc+nm+4);
3099 for (i=0; i < count; ++i) {
3100 stbtt_uint32 loc = nm + 6 + 12 * i;
3101 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
3102 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
3103 *length = ttUSHORT(fc+loc+8);
3104 return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
3105 }
3106 }
3107 return NULL;
3108}
3109
3110static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
3111{
3112 stbtt_int32 i;
3113 stbtt_int32 count = ttUSHORT(fc+nm+2);
3114 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
3115
3116 for (i=0; i < count; ++i) {
3117 stbtt_uint32 loc = nm + 6 + 12 * i;
3118 stbtt_int32 id = ttUSHORT(fc+loc+6);
3119 if (id == target_id) {
3120
3121 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
3122
3123
3124 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
3125 stbtt_int32 slen = ttUSHORT(fc+loc+8);
3126 stbtt_int32 off = ttUSHORT(fc+loc+10);
3127
3128
3129 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
3130 if (matchlen >= 0) {
3131
3132 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) {
3133 slen = ttUSHORT(fc+loc+12+8);
3134 off = ttUSHORT(fc+loc+12+10);
3135 if (slen == 0) {
3136 if (matchlen == nlen)
3137 return 1;
3138 } else if (matchlen < nlen && name[matchlen] == ' ') {
3139 ++matchlen;
3140 if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
3141 return 1;
3142 }
3143 } else {
3144
3145 if (matchlen == nlen)
3146 return 1;
3147 }
3148 }
3149 }
3150
3151
3152 }
3153 }
3154 return 0;
3155}
3156
3157static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
3158{
3159 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
3160 stbtt_uint32 nm,hd;
3161 if (!stbtt__isfont(fc+offset)) return 0;
3162
3163
3164 if (flags) {
3165 hd = stbtt__find_table(fc, offset, "head");
3166 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
3167 }
3168
3169 nm = stbtt__find_table(fc, offset, "name");
3170 if (!nm) return 0;
3171
3172 if (flags) {
3173
3174 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
3175 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
3176 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
3177 } else {
3178 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
3179 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
3180 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
3181 }
3182
3183 return 0;
3184}
3185
3186STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags)
3187{
3188 stbtt_int32 i;
3189 for (i=0;;++i) {
3190 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
3191 if (off < 0) return off;
3192 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
3193 return off;
3194 }
3195}
3196
3197#endif
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243