File indexing completed on 2026-04-09 07:49:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 #if 0
0278 #define STB_TRUETYPE_IMPLEMENTATION
0279 #include "stb_truetype.h"
0280
0281 unsigned char ttf_buffer[1<<20];
0282 unsigned char temp_bitmap[512*512];
0283
0284 stbtt_bakedchar cdata[96];
0285 GLuint ftex;
0286
0287 void my_stbtt_initfont(void)
0288 {
0289 fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
0290 stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata);
0291
0292 glGenTextures(1, &ftex);
0293 glBindTexture(GL_TEXTURE_2D, ftex);
0294 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
0295
0296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
0297 }
0298
0299 void my_stbtt_print(float x, float y, char *text)
0300 {
0301
0302 glEnable(GL_BLEND);
0303 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
0304 glEnable(GL_TEXTURE_2D);
0305 glBindTexture(GL_TEXTURE_2D, ftex);
0306 glBegin(GL_QUADS);
0307 while (*text) {
0308 if (*text >= 32 && *text < 128) {
0309 stbtt_aligned_quad q;
0310 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);
0311 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
0312 glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
0313 glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
0314 glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
0315 }
0316 ++text;
0317 }
0318 glEnd();
0319 }
0320 #endif
0321
0322
0323
0324
0325
0326
0327 #if 0
0328 #include <stdio.h>
0329 #define STB_TRUETYPE_IMPLEMENTATION
0330 #include "stb_truetype.h"
0331
0332 char ttf_buffer[1<<25];
0333
0334 int main(int argc, char **argv)
0335 {
0336 stbtt_fontinfo font;
0337 unsigned char *bitmap;
0338 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
0339
0340 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
0341
0342 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
0343 bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
0344
0345 for (j=0; j < h; ++j) {
0346 for (i=0; i < w; ++i)
0347 putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
0348 putchar('\n');
0349 }
0350 return 0;
0351 }
0352 #endif
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371 #if 0
0372 char buffer[24<<20];
0373 unsigned char screen[20][79];
0374
0375 int main(int arg, char **argv)
0376 {
0377 stbtt_fontinfo font;
0378 int i,j,ascent,baseline,ch=0;
0379 float scale, xpos=2;
0380 char *text = "Heljo World!";
0381
0382 fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
0383 stbtt_InitFont(&font, buffer, 0);
0384
0385 scale = stbtt_ScaleForPixelHeight(&font, 15);
0386 stbtt_GetFontVMetrics(&font, &ascent,0,0);
0387 baseline = (int) (ascent*scale);
0388
0389 while (text[ch]) {
0390 int advance,lsb,x0,y0,x1,y1;
0391 float x_shift = xpos - (float) floor(xpos);
0392 stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
0393 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
0394 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
0395
0396
0397
0398
0399 xpos += (advance * scale);
0400 if (text[ch+1])
0401 xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
0402 ++ch;
0403 }
0404
0405 for (j=0; j < 20; ++j) {
0406 for (i=0; i < 78; ++i)
0407 putchar(" .:ioVM@"[screen[j][i]>>5]);
0408 putchar('\n');
0409 }
0410
0411 return 0;
0412 }
0413 #endif
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425 #ifdef STB_TRUETYPE_IMPLEMENTATION
0426
0427 #ifndef stbtt_uint8
0428 typedef unsigned char stbtt_uint8;
0429 typedef signed char stbtt_int8;
0430 typedef unsigned short stbtt_uint16;
0431 typedef signed short stbtt_int16;
0432 typedef unsigned int stbtt_uint32;
0433 typedef signed int stbtt_int32;
0434 #endif
0435
0436 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
0437 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
0438
0439
0440 #ifndef STBTT_ifloor
0441 #include <math.h>
0442 #define STBTT_ifloor(x) ((int) floor(x))
0443 #define STBTT_iceil(x) ((int) ceil(x))
0444 #endif
0445
0446 #ifndef STBTT_sqrt
0447 #include <math.h>
0448 #define STBTT_sqrt(x) sqrt(x)
0449 #define STBTT_pow(x,y) pow(x,y)
0450 #endif
0451
0452 #ifndef STBTT_fmod
0453 #include <math.h>
0454 #define STBTT_fmod(x,y) fmod(x,y)
0455 #endif
0456
0457 #ifndef STBTT_cos
0458 #include <math.h>
0459 #define STBTT_cos(x) cos(x)
0460 #define STBTT_acos(x) acos(x)
0461 #endif
0462
0463 #ifndef STBTT_fabs
0464 #include <math.h>
0465 #define STBTT_fabs(x) fabs(x)
0466 #endif
0467
0468
0469 #ifndef STBTT_malloc
0470 #include <stdlib.h>
0471 #define STBTT_malloc(x,u) ((void)(u),malloc(x))
0472 #define STBTT_free(x,u) ((void)(u),free(x))
0473 #endif
0474
0475 #ifndef STBTT_assert
0476 #include <assert.h>
0477 #define STBTT_assert(x) assert(x)
0478 #endif
0479
0480 #ifndef STBTT_strlen
0481 #include <string.h>
0482 #define STBTT_strlen(x) strlen(x)
0483 #endif
0484
0485 #ifndef STBTT_memcpy
0486 #include <string.h>
0487 #define STBTT_memcpy memcpy
0488 #define STBTT_memset memset
0489 #endif
0490 #endif
0491
0492
0493
0494
0495
0496
0497
0498
0499 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
0500 #define __STB_INCLUDE_STB_TRUETYPE_H__
0501
0502 #ifdef STBTT_STATIC
0503 #define STBTT_DEF static
0504 #else
0505 #define STBTT_DEF extern
0506 #endif
0507
0508 #ifdef __cplusplus
0509 extern "C" {
0510 #endif
0511
0512
0513 typedef struct
0514 {
0515 unsigned char *data;
0516 int cursor;
0517 int size;
0518 } stbtt__buf;
0519
0520
0521
0522
0523
0524
0525
0526
0527 typedef struct
0528 {
0529 unsigned short x0,y0,x1,y1;
0530 float xoff,yoff,xadvance;
0531 } stbtt_bakedchar;
0532
0533 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
0534 float pixel_height,
0535 unsigned char *pixels, int pw, int ph,
0536 int first_char, int num_chars,
0537 stbtt_bakedchar *chardata);
0538
0539
0540
0541
0542
0543 typedef struct
0544 {
0545 float x0,y0,s0,t0;
0546 float x1,y1,s1,t1;
0547 } stbtt_aligned_quad;
0548
0549 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph,
0550 int char_index,
0551 float *xpos, float *ypos,
0552 stbtt_aligned_quad *q,
0553 int opengl_fillrule);
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575 typedef struct
0576 {
0577 unsigned short x0,y0,x1,y1;
0578 float xoff,yoff,xadvance;
0579 float xoff2,yoff2;
0580 } stbtt_packedchar;
0581
0582 typedef struct stbtt_pack_context stbtt_pack_context;
0583 typedef struct stbtt_fontinfo stbtt_fontinfo;
0584 #ifndef STB_RECT_PACK_VERSION
0585 typedef struct stbrp_rect stbrp_rect;
0586 #endif
0587
0588 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
0600
0601
0602 #define STBTT_POINT_SIZE(x) (-(x))
0603
0604 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
0605 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619 typedef struct
0620 {
0621 float font_size;
0622 int first_unicode_codepoint_in_range;
0623 int *array_of_unicode_codepoints;
0624 int num_chars;
0625 stbtt_packedchar *chardata_for_range;
0626 unsigned char h_oversample, v_oversample;
0627 } stbtt_pack_range;
0628
0629 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
0630
0631
0632
0633
0634
0635 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
0652
0653
0654
0655
0656
0657 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph,
0658 int char_index,
0659 float *xpos, float *ypos,
0660 stbtt_aligned_quad *q,
0661 int align_to_integer);
0662
0663 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
0664 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
0665 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 struct stbtt_pack_context {
0679 void *user_allocator_context;
0680 void *pack_info;
0681 int width;
0682 int height;
0683 int stride_in_bytes;
0684 int padding;
0685 int skip_missing;
0686 unsigned int h_oversample, v_oversample;
0687 unsigned char *pixels;
0688 void *nodes;
0689 };
0690
0691
0692
0693
0694
0695
0696
0697 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
0698
0699
0700
0701
0702
0703
0704 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
0705
0706
0707
0708
0709
0710
0711
0712
0713 struct stbtt_fontinfo
0714 {
0715 void * userdata;
0716 unsigned char * data;
0717 int fontstart;
0718
0719 int numGlyphs;
0720
0721 int loca,head,glyf,hhea,hmtx,kern,gpos,svg;
0722 int index_map;
0723 int indexToLocFormat;
0724
0725 stbtt__buf cff;
0726 stbtt__buf charstrings;
0727 stbtt__buf gsubrs;
0728 stbtt__buf subrs;
0729 stbtt__buf fontdicts;
0730 stbtt__buf fdselect;
0731 };
0732
0733 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
0759
0760
0761
0762
0763
0764
0765
0766 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
0767
0768
0769
0770
0771 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
0772
0773
0774
0775
0776
0777
0778
0779 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
0780
0781
0782
0783
0784
0785 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
0786
0787
0788 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
0789
0790
0791
0792
0793 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
0794
0795
0796 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
0797
0798
0799 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
0800 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
0801 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
0802
0803
0804 typedef struct stbtt_kerningentry
0805 {
0806 int glyph1;
0807 int glyph2;
0808 int advance;
0809 } stbtt_kerningentry;
0810
0811 STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
0812 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823 #ifndef STBTT_vmove
0824 enum {
0825 STBTT_vmove=1,
0826 STBTT_vline,
0827 STBTT_vcurve,
0828 STBTT_vcubic
0829 };
0830 #endif
0831
0832 #ifndef stbtt_vertex
0833
0834 #define stbtt_vertex_type short
0835 typedef struct
0836 {
0837 stbtt_vertex_type x,y,cx,cy,cx1,cy1;
0838 unsigned char type,padding;
0839 } stbtt_vertex;
0840 #endif
0841
0842 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
0843
0844
0845 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
0846 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
0858
0859
0860 STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
0861 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
0862 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
0863
0864
0865
0866
0867
0868
0869
0870
0871 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
0872
0873
0874 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
0875
0876
0877
0878
0879
0880
0881
0882
0883 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
0884
0885
0886
0887 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
0888
0889
0890
0891
0892
0893 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
0894
0895
0896
0897 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
0898
0899
0900
0901 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
0902
0903
0904
0905
0906
0907
0908 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
0909
0910
0911
0912
0913
0914 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
0915 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
0916 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
0917 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
0918 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
0919 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
0920 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
0921
0922
0923
0924 typedef struct
0925 {
0926 int w,h,stride;
0927 unsigned char *pixels;
0928 } stbtt__bitmap;
0929
0930
0931 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result,
0932 float flatness_in_pixels,
0933 stbtt_vertex *vertices,
0934 int num_verts,
0935 float scale_x, float scale_y,
0936 float shift_x, float shift_y,
0937 int x_off, int y_off,
0938 int invert,
0939 void *userdata);
0940
0941
0942
0943
0944
0945 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
0946
0947
0948 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
0949 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
1022
1023
1024
1025
1026 #define STBTT_MACSTYLE_DONTCARE 0
1027 #define STBTT_MACSTYLE_BOLD 1
1028 #define STBTT_MACSTYLE_ITALIC 2
1029 #define STBTT_MACSTYLE_UNDERSCORE 4
1030 #define STBTT_MACSTYLE_NONE 8
1031
1032 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
1033
1034
1035
1036 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
1037
1038
1039
1040
1041
1042
1043
1044 enum {
1045 STBTT_PLATFORM_ID_UNICODE =0,
1046 STBTT_PLATFORM_ID_MAC =1,
1047 STBTT_PLATFORM_ID_ISO =2,
1048 STBTT_PLATFORM_ID_MICROSOFT =3
1049 };
1050
1051 enum {
1052 STBTT_UNICODE_EID_UNICODE_1_0 =0,
1053 STBTT_UNICODE_EID_UNICODE_1_1 =1,
1054 STBTT_UNICODE_EID_ISO_10646 =2,
1055 STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
1056 STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
1057 };
1058
1059 enum {
1060 STBTT_MS_EID_SYMBOL =0,
1061 STBTT_MS_EID_UNICODE_BMP =1,
1062 STBTT_MS_EID_SHIFTJIS =2,
1063 STBTT_MS_EID_UNICODE_FULL =10
1064 };
1065
1066 enum {
1067 STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
1068 STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
1069 STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
1070 STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
1071 };
1072
1073 enum {
1074
1075 STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
1076 STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
1077 STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
1078 STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
1079 STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
1080 STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
1081 };
1082
1083 enum {
1084 STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
1085 STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
1086 STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
1087 STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
1088 STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
1089 STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
1090 STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
1091 };
1092
1093 #ifdef __cplusplus
1094 }
1095 #endif
1096
1097 #endif
1098
1099
1100
1101
1102
1103
1104
1105
1106 #ifdef STB_TRUETYPE_IMPLEMENTATION
1107
1108 #ifndef STBTT_MAX_OVERSAMPLE
1109 #define STBTT_MAX_OVERSAMPLE 8
1110 #endif
1111
1112 #if STBTT_MAX_OVERSAMPLE > 255
1113 #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
1114 #endif
1115
1116 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
1117
1118 #ifndef STBTT_RASTERIZER_VERSION
1119 #define STBTT_RASTERIZER_VERSION 2
1120 #endif
1121
1122 #ifdef _MSC_VER
1123 #define STBTT__NOTUSED(v) (void)(v)
1124 #else
1125 #define STBTT__NOTUSED(v) (void)sizeof(v)
1126 #endif
1127
1128
1129
1130
1131
1132
1133 static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
1134 {
1135 if (b->cursor >= b->size)
1136 return 0;
1137 return b->data[b->cursor++];
1138 }
1139
1140 static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
1141 {
1142 if (b->cursor >= b->size)
1143 return 0;
1144 return b->data[b->cursor];
1145 }
1146
1147 static void stbtt__buf_seek(stbtt__buf *b, int o)
1148 {
1149 STBTT_assert(!(o > b->size || o < 0));
1150 b->cursor = (o > b->size || o < 0) ? b->size : o;
1151 }
1152
1153 static void stbtt__buf_skip(stbtt__buf *b, int o)
1154 {
1155 stbtt__buf_seek(b, b->cursor + o);
1156 }
1157
1158 static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
1159 {
1160 stbtt_uint32 v = 0;
1161 int i;
1162 STBTT_assert(n >= 1 && n <= 4);
1163 for (i = 0; i < n; i++)
1164 v = (v << 8) | stbtt__buf_get8(b);
1165 return v;
1166 }
1167
1168 static stbtt__buf stbtt__new_buf(const void *p, size_t size)
1169 {
1170 stbtt__buf r;
1171 STBTT_assert(size < 0x40000000);
1172 r.data = (stbtt_uint8*) p;
1173 r.size = (int) size;
1174 r.cursor = 0;
1175 return r;
1176 }
1177
1178 #define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
1179 #define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
1180
1181 static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
1182 {
1183 stbtt__buf r = stbtt__new_buf(NULL, 0);
1184 if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
1185 r.data = b->data + o;
1186 r.size = s;
1187 return r;
1188 }
1189
1190 static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
1191 {
1192 int count, start, offsize;
1193 start = b->cursor;
1194 count = stbtt__buf_get16(b);
1195 if (count) {
1196 offsize = stbtt__buf_get8(b);
1197 STBTT_assert(offsize >= 1 && offsize <= 4);
1198 stbtt__buf_skip(b, offsize * count);
1199 stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
1200 }
1201 return stbtt__buf_range(b, start, b->cursor - start);
1202 }
1203
1204 static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
1205 {
1206 int b0 = stbtt__buf_get8(b);
1207 if (b0 >= 32 && b0 <= 246) return b0 - 139;
1208 else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
1209 else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
1210 else if (b0 == 28) return stbtt__buf_get16(b);
1211 else if (b0 == 29) return stbtt__buf_get32(b);
1212 STBTT_assert(0);
1213 return 0;
1214 }
1215
1216 static void stbtt__cff_skip_operand(stbtt__buf *b) {
1217 int v, b0 = stbtt__buf_peek8(b);
1218 STBTT_assert(b0 >= 28);
1219 if (b0 == 30) {
1220 stbtt__buf_skip(b, 1);
1221 while (b->cursor < b->size) {
1222 v = stbtt__buf_get8(b);
1223 if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
1224 break;
1225 }
1226 } else {
1227 stbtt__cff_int(b);
1228 }
1229 }
1230
1231 static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
1232 {
1233 stbtt__buf_seek(b, 0);
1234 while (b->cursor < b->size) {
1235 int start = b->cursor, end, op;
1236 while (stbtt__buf_peek8(b) >= 28)
1237 stbtt__cff_skip_operand(b);
1238 end = b->cursor;
1239 op = stbtt__buf_get8(b);
1240 if (op == 12) op = stbtt__buf_get8(b) | 0x100;
1241 if (op == key) return stbtt__buf_range(b, start, end-start);
1242 }
1243 return stbtt__buf_range(b, 0, 0);
1244 }
1245
1246 static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
1247 {
1248 int i;
1249 stbtt__buf operands = stbtt__dict_get(b, key);
1250 for (i = 0; i < outcount && operands.cursor < operands.size; i++)
1251 out[i] = stbtt__cff_int(&operands);
1252 }
1253
1254 static int stbtt__cff_index_count(stbtt__buf *b)
1255 {
1256 stbtt__buf_seek(b, 0);
1257 return stbtt__buf_get16(b);
1258 }
1259
1260 static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
1261 {
1262 int count, offsize, start, end;
1263 stbtt__buf_seek(&b, 0);
1264 count = stbtt__buf_get16(&b);
1265 offsize = stbtt__buf_get8(&b);
1266 STBTT_assert(i >= 0 && i < count);
1267 STBTT_assert(offsize >= 1 && offsize <= 4);
1268 stbtt__buf_skip(&b, i*offsize);
1269 start = stbtt__buf_get(&b, offsize);
1270 end = stbtt__buf_get(&b, offsize);
1271 return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
1272 }
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
1283 #define ttCHAR(p) (* (stbtt_int8 *) (p))
1284 #define ttFixed(p) ttLONG(p)
1285
1286 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
1287 static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
1288 static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1289 static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1290
1291 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
1292 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
1293
1294 static int stbtt__isfont(stbtt_uint8 *font)
1295 {
1296
1297 if (stbtt_tag4(font, '1',0,0,0)) return 1;
1298 if (stbtt_tag(font, "typ1")) return 1;
1299 if (stbtt_tag(font, "OTTO")) return 1;
1300 if (stbtt_tag4(font, 0,1,0,0)) return 1;
1301 if (stbtt_tag(font, "true")) return 1;
1302 return 0;
1303 }
1304
1305
1306 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
1307 {
1308 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
1309 stbtt_uint32 tabledir = fontstart + 12;
1310 stbtt_int32 i;
1311 for (i=0; i < num_tables; ++i) {
1312 stbtt_uint32 loc = tabledir + 16*i;
1313 if (stbtt_tag(data+loc+0, tag))
1314 return ttULONG(data+loc+8);
1315 }
1316 return 0;
1317 }
1318
1319 static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
1320 {
1321
1322 if (stbtt__isfont(font_collection))
1323 return index == 0 ? 0 : -1;
1324
1325
1326 if (stbtt_tag(font_collection, "ttcf")) {
1327
1328 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1329 stbtt_int32 n = ttLONG(font_collection+8);
1330 if (index >= n)
1331 return -1;
1332 return ttULONG(font_collection+12+index*4);
1333 }
1334 }
1335 return -1;
1336 }
1337
1338 static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
1339 {
1340
1341 if (stbtt__isfont(font_collection))
1342 return 1;
1343
1344
1345 if (stbtt_tag(font_collection, "ttcf")) {
1346
1347 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1348 return ttLONG(font_collection+8);
1349 }
1350 }
1351 return 0;
1352 }
1353
1354 static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
1355 {
1356 stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
1357 stbtt__buf pdict;
1358 stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
1359 if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
1360 pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
1361 stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
1362 if (!subrsoff) return stbtt__new_buf(NULL, 0);
1363 stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
1364 return stbtt__cff_get_index(&cff);
1365 }
1366
1367
1368 static int stbtt__get_svg(stbtt_fontinfo *info)
1369 {
1370 stbtt_uint32 t;
1371 if (info->svg < 0) {
1372 t = stbtt__find_table(info->data, info->fontstart, "SVG ");
1373 if (t) {
1374 stbtt_uint32 offset = ttULONG(info->data + t + 2);
1375 info->svg = t + offset;
1376 } else {
1377 info->svg = 0;
1378 }
1379 }
1380 return info->svg;
1381 }
1382
1383 static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
1384 {
1385 stbtt_uint32 cmap, t;
1386 stbtt_int32 i,numTables;
1387
1388 info->data = data;
1389 info->fontstart = fontstart;
1390 info->cff = stbtt__new_buf(NULL, 0);
1391
1392 cmap = stbtt__find_table(data, fontstart, "cmap");
1393 info->loca = stbtt__find_table(data, fontstart, "loca");
1394 info->head = stbtt__find_table(data, fontstart, "head");
1395 info->glyf = stbtt__find_table(data, fontstart, "glyf");
1396 info->hhea = stbtt__find_table(data, fontstart, "hhea");
1397 info->hmtx = stbtt__find_table(data, fontstart, "hmtx");
1398 info->kern = stbtt__find_table(data, fontstart, "kern");
1399 info->gpos = stbtt__find_table(data, fontstart, "GPOS");
1400
1401 if (!cmap || !info->head || !info->hhea || !info->hmtx)
1402 return 0;
1403 if (info->glyf) {
1404
1405 if (!info->loca) return 0;
1406 } else {
1407
1408 stbtt__buf b, topdict, topdictidx;
1409 stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
1410 stbtt_uint32 cff;
1411
1412 cff = stbtt__find_table(data, fontstart, "CFF ");
1413 if (!cff) return 0;
1414
1415 info->fontdicts = stbtt__new_buf(NULL, 0);
1416 info->fdselect = stbtt__new_buf(NULL, 0);
1417
1418
1419 info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
1420 b = info->cff;
1421
1422
1423 stbtt__buf_skip(&b, 2);
1424 stbtt__buf_seek(&b, stbtt__buf_get8(&b));
1425
1426
1427
1428 stbtt__cff_get_index(&b);
1429 topdictidx = stbtt__cff_get_index(&b);
1430 topdict = stbtt__cff_index_get(topdictidx, 0);
1431 stbtt__cff_get_index(&b);
1432 info->gsubrs = stbtt__cff_get_index(&b);
1433
1434 stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
1435 stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
1436 stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
1437 stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
1438 info->subrs = stbtt__get_subrs(b, topdict);
1439
1440
1441 if (cstype != 2) return 0;
1442 if (charstrings == 0) return 0;
1443
1444 if (fdarrayoff) {
1445
1446 if (!fdselectoff) return 0;
1447 stbtt__buf_seek(&b, fdarrayoff);
1448 info->fontdicts = stbtt__cff_get_index(&b);
1449 info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
1450 }
1451
1452 stbtt__buf_seek(&b, charstrings);
1453 info->charstrings = stbtt__cff_get_index(&b);
1454 }
1455
1456 t = stbtt__find_table(data, fontstart, "maxp");
1457 if (t)
1458 info->numGlyphs = ttUSHORT(data+t+4);
1459 else
1460 info->numGlyphs = 0xffff;
1461
1462 info->svg = -1;
1463
1464
1465
1466
1467 numTables = ttUSHORT(data + cmap + 2);
1468 info->index_map = 0;
1469 for (i=0; i < numTables; ++i) {
1470 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1471
1472 switch(ttUSHORT(data+encoding_record)) {
1473 case STBTT_PLATFORM_ID_MICROSOFT:
1474 switch (ttUSHORT(data+encoding_record+2)) {
1475 case STBTT_MS_EID_UNICODE_BMP:
1476 case STBTT_MS_EID_UNICODE_FULL:
1477
1478 info->index_map = cmap + ttULONG(data+encoding_record+4);
1479 break;
1480 }
1481 break;
1482 case STBTT_PLATFORM_ID_UNICODE:
1483
1484
1485 info->index_map = cmap + ttULONG(data+encoding_record+4);
1486 break;
1487 }
1488 }
1489 if (info->index_map == 0)
1490 return 0;
1491
1492 info->indexToLocFormat = ttUSHORT(data+info->head + 50);
1493 return 1;
1494 }
1495
1496 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
1497 {
1498 stbtt_uint8 *data = info->data;
1499 stbtt_uint32 index_map = info->index_map;
1500
1501 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1502 if (format == 0) {
1503 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1504 if (unicode_codepoint < bytes-6)
1505 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1506 return 0;
1507 } else if (format == 6) {
1508 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1509 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1510 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1511 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1512 return 0;
1513 } else if (format == 2) {
1514 STBTT_assert(0);
1515 return 0;
1516 } else if (format == 4) {
1517 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1518 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1519 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1520 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1521
1522
1523 stbtt_uint32 endCount = index_map + 14;
1524 stbtt_uint32 search = endCount;
1525
1526 if (unicode_codepoint > 0xffff)
1527 return 0;
1528
1529
1530
1531 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1532 search += rangeShift*2;
1533
1534
1535 search -= 2;
1536 while (entrySelector) {
1537 stbtt_uint16 end;
1538 searchRange >>= 1;
1539 end = ttUSHORT(data + search + searchRange*2);
1540 if (unicode_codepoint > end)
1541 search += searchRange*2;
1542 --entrySelector;
1543 }
1544 search += 2;
1545
1546 {
1547 stbtt_uint16 offset, start, last;
1548 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
1549
1550 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1551 last = ttUSHORT(data + endCount + 2*item);
1552 if (unicode_codepoint < start || unicode_codepoint > last)
1553 return 0;
1554
1555 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1556 if (offset == 0)
1557 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1558
1559 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1560 }
1561 } else if (format == 12 || format == 13) {
1562 stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1563 stbtt_int32 low,high;
1564 low = 0; high = (stbtt_int32)ngroups;
1565
1566 while (low < high) {
1567 stbtt_int32 mid = low + ((high-low) >> 1);
1568 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1569 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1570 if ((stbtt_uint32) unicode_codepoint < start_char)
1571 high = mid;
1572 else if ((stbtt_uint32) unicode_codepoint > end_char)
1573 low = mid+1;
1574 else {
1575 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1576 if (format == 12)
1577 return start_glyph + unicode_codepoint-start_char;
1578 else
1579 return start_glyph;
1580 }
1581 }
1582 return 0;
1583 }
1584
1585 STBTT_assert(0);
1586 return 0;
1587 }
1588
1589 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
1590 {
1591 return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
1592 }
1593
1594 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1595 {
1596 v->type = type;
1597 v->x = (stbtt_int16) x;
1598 v->y = (stbtt_int16) y;
1599 v->cx = (stbtt_int16) cx;
1600 v->cy = (stbtt_int16) cy;
1601 }
1602
1603 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
1604 {
1605 int g1,g2;
1606
1607 STBTT_assert(!info->cff.size);
1608
1609 if (glyph_index >= info->numGlyphs) return -1;
1610 if (info->indexToLocFormat >= 2) return -1;
1611
1612 if (info->indexToLocFormat == 0) {
1613 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
1614 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
1615 } else {
1616 g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
1617 g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
1618 }
1619
1620 return g1==g2 ? -1 : g1;
1621 }
1622
1623 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
1624
1625 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
1626 {
1627 if (info->cff.size) {
1628 stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
1629 } else {
1630 int g = stbtt__GetGlyfOffset(info, glyph_index);
1631 if (g < 0) return 0;
1632
1633 if (x0) *x0 = ttSHORT(info->data + g + 2);
1634 if (y0) *y0 = ttSHORT(info->data + g + 4);
1635 if (x1) *x1 = ttSHORT(info->data + g + 6);
1636 if (y1) *y1 = ttSHORT(info->data + g + 8);
1637 }
1638 return 1;
1639 }
1640
1641 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
1642 {
1643 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
1644 }
1645
1646 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
1647 {
1648 stbtt_int16 numberOfContours;
1649 int g;
1650 if (info->cff.size)
1651 return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
1652 g = stbtt__GetGlyfOffset(info, glyph_index);
1653 if (g < 0) return 1;
1654 numberOfContours = ttSHORT(info->data + g);
1655 return numberOfContours == 0;
1656 }
1657
1658 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
1659 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1660 {
1661 if (start_off) {
1662 if (was_off)
1663 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1664 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
1665 } else {
1666 if (was_off)
1667 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
1668 else
1669 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
1670 }
1671 return num_vertices;
1672 }
1673
1674 static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
1675 {
1676 stbtt_int16 numberOfContours;
1677 stbtt_uint8 *endPtsOfContours;
1678 stbtt_uint8 *data = info->data;
1679 stbtt_vertex *vertices=0;
1680 int num_vertices=0;
1681 int g = stbtt__GetGlyfOffset(info, glyph_index);
1682
1683 *pvertices = NULL;
1684
1685 if (g < 0) return 0;
1686
1687 numberOfContours = ttSHORT(data + g);
1688
1689 if (numberOfContours > 0) {
1690 stbtt_uint8 flags=0,flagcount;
1691 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1692 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1693 stbtt_uint8 *points;
1694 endPtsOfContours = (data + g + 10);
1695 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1696 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1697
1698 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1699
1700 m = n + 2*numberOfContours;
1701 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
1702 if (vertices == 0)
1703 return 0;
1704
1705 next_move = 0;
1706 flagcount=0;
1707
1708
1709
1710
1711
1712 off = m - n;
1713
1714
1715
1716 for (i=0; i < n; ++i) {
1717 if (flagcount == 0) {
1718 flags = *points++;
1719 if (flags & 8)
1720 flagcount = *points++;
1721 } else
1722 --flagcount;
1723 vertices[off+i].type = flags;
1724 }
1725
1726
1727 x=0;
1728 for (i=0; i < n; ++i) {
1729 flags = vertices[off+i].type;
1730 if (flags & 2) {
1731 stbtt_int16 dx = *points++;
1732 x += (flags & 16) ? dx : -dx;
1733 } else {
1734 if (!(flags & 16)) {
1735 x = x + (stbtt_int16) (points[0]*256 + points[1]);
1736 points += 2;
1737 }
1738 }
1739 vertices[off+i].x = (stbtt_int16) x;
1740 }
1741
1742
1743 y=0;
1744 for (i=0; i < n; ++i) {
1745 flags = vertices[off+i].type;
1746 if (flags & 4) {
1747 stbtt_int16 dy = *points++;
1748 y += (flags & 32) ? dy : -dy;
1749 } else {
1750 if (!(flags & 32)) {
1751 y = y + (stbtt_int16) (points[0]*256 + points[1]);
1752 points += 2;
1753 }
1754 }
1755 vertices[off+i].y = (stbtt_int16) y;
1756 }
1757
1758
1759 num_vertices=0;
1760 sx = sy = cx = cy = scx = scy = 0;
1761 for (i=0; i < n; ++i) {
1762 flags = vertices[off+i].type;
1763 x = (stbtt_int16) vertices[off+i].x;
1764 y = (stbtt_int16) vertices[off+i].y;
1765
1766 if (next_move == i) {
1767 if (i != 0)
1768 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1769
1770
1771 start_off = !(flags & 1);
1772 if (start_off) {
1773
1774
1775 scx = x;
1776 scy = y;
1777 if (!(vertices[off+i+1].type & 1)) {
1778
1779 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1780 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1781 } else {
1782
1783 sx = (stbtt_int32) vertices[off+i+1].x;
1784 sy = (stbtt_int32) vertices[off+i+1].y;
1785 ++i;
1786 }
1787 } else {
1788 sx = x;
1789 sy = y;
1790 }
1791 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
1792 was_off = 0;
1793 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1794 ++j;
1795 } else {
1796 if (!(flags & 1)) {
1797 if (was_off)
1798 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1799 cx = x;
1800 cy = y;
1801 was_off = 1;
1802 } else {
1803 if (was_off)
1804 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
1805 else
1806 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
1807 was_off = 0;
1808 }
1809 }
1810 }
1811 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1812 } else if (numberOfContours < 0) {
1813
1814 int more = 1;
1815 stbtt_uint8 *comp = data + g + 10;
1816 num_vertices = 0;
1817 vertices = 0;
1818 while (more) {
1819 stbtt_uint16 flags, gidx;
1820 int comp_num_verts = 0, i;
1821 stbtt_vertex *comp_verts = 0, *tmp = 0;
1822 float mtx[6] = {1,0,0,1,0,0}, m, n;
1823
1824 flags = ttSHORT(comp); comp+=2;
1825 gidx = ttSHORT(comp); comp+=2;
1826
1827 if (flags & 2) {
1828 if (flags & 1) {
1829 mtx[4] = ttSHORT(comp); comp+=2;
1830 mtx[5] = ttSHORT(comp); comp+=2;
1831 } else {
1832 mtx[4] = ttCHAR(comp); comp+=1;
1833 mtx[5] = ttCHAR(comp); comp+=1;
1834 }
1835 }
1836 else {
1837
1838 STBTT_assert(0);
1839 }
1840 if (flags & (1<<3)) {
1841 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1842 mtx[1] = mtx[2] = 0;
1843 } else if (flags & (1<<6)) {
1844 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1845 mtx[1] = mtx[2] = 0;
1846 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1847 } else if (flags & (1<<7)) {
1848 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1849 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1850 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1851 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1852 }
1853
1854
1855 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1856 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1857
1858
1859 comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
1860 if (comp_num_verts > 0) {
1861
1862 for (i = 0; i < comp_num_verts; ++i) {
1863 stbtt_vertex* v = &comp_verts[i];
1864 stbtt_vertex_type x,y;
1865 x=v->x; y=v->y;
1866 v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1867 v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1868 x=v->cx; y=v->cy;
1869 v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
1870 v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
1871 }
1872
1873 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
1874 if (!tmp) {
1875 if (vertices) STBTT_free(vertices, info->userdata);
1876 if (comp_verts) STBTT_free(comp_verts, info->userdata);
1877 return 0;
1878 }
1879 if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
1880 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
1881 if (vertices) STBTT_free(vertices, info->userdata);
1882 vertices = tmp;
1883 STBTT_free(comp_verts, info->userdata);
1884 num_vertices += comp_num_verts;
1885 }
1886
1887 more = flags & (1<<5);
1888 }
1889 } else {
1890
1891 }
1892
1893 *pvertices = vertices;
1894 return num_vertices;
1895 }
1896
1897 typedef struct
1898 {
1899 int bounds;
1900 int started;
1901 float first_x, first_y;
1902 float x, y;
1903 stbtt_int32 min_x, max_x, min_y, max_y;
1904
1905 stbtt_vertex *pvertices;
1906 int num_vertices;
1907 } stbtt__csctx;
1908
1909 #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
1910
1911 static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
1912 {
1913 if (x > c->max_x || !c->started) c->max_x = x;
1914 if (y > c->max_y || !c->started) c->max_y = y;
1915 if (x < c->min_x || !c->started) c->min_x = x;
1916 if (y < c->min_y || !c->started) c->min_y = y;
1917 c->started = 1;
1918 }
1919
1920 static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
1921 {
1922 if (c->bounds) {
1923 stbtt__track_vertex(c, x, y);
1924 if (type == STBTT_vcubic) {
1925 stbtt__track_vertex(c, cx, cy);
1926 stbtt__track_vertex(c, cx1, cy1);
1927 }
1928 } else {
1929 stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
1930 c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
1931 c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
1932 }
1933 c->num_vertices++;
1934 }
1935
1936 static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
1937 {
1938 if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
1939 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
1940 }
1941
1942 static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
1943 {
1944 stbtt__csctx_close_shape(ctx);
1945 ctx->first_x = ctx->x = ctx->x + dx;
1946 ctx->first_y = ctx->y = ctx->y + dy;
1947 stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1948 }
1949
1950 static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
1951 {
1952 ctx->x += dx;
1953 ctx->y += dy;
1954 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
1955 }
1956
1957 static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
1958 {
1959 float cx1 = ctx->x + dx1;
1960 float cy1 = ctx->y + dy1;
1961 float cx2 = cx1 + dx2;
1962 float cy2 = cy1 + dy2;
1963 ctx->x = cx2 + dx3;
1964 ctx->y = cy2 + dy3;
1965 stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
1966 }
1967
1968 static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
1969 {
1970 int count = stbtt__cff_index_count(&idx);
1971 int bias = 107;
1972 if (count >= 33900)
1973 bias = 32768;
1974 else if (count >= 1240)
1975 bias = 1131;
1976 n += bias;
1977 if (n < 0 || n >= count)
1978 return stbtt__new_buf(NULL, 0);
1979 return stbtt__cff_index_get(idx, n);
1980 }
1981
1982 static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
1983 {
1984 stbtt__buf fdselect = info->fdselect;
1985 int nranges, start, end, v, fmt, fdselector = -1, i;
1986
1987 stbtt__buf_seek(&fdselect, 0);
1988 fmt = stbtt__buf_get8(&fdselect);
1989 if (fmt == 0) {
1990
1991 stbtt__buf_skip(&fdselect, glyph_index);
1992 fdselector = stbtt__buf_get8(&fdselect);
1993 } else if (fmt == 3) {
1994 nranges = stbtt__buf_get16(&fdselect);
1995 start = stbtt__buf_get16(&fdselect);
1996 for (i = 0; i < nranges; i++) {
1997 v = stbtt__buf_get8(&fdselect);
1998 end = stbtt__buf_get16(&fdselect);
1999 if (glyph_index >= start && glyph_index < end) {
2000 fdselector = v;
2001 break;
2002 }
2003 start = end;
2004 }
2005 }
2006 if (fdselector == -1) stbtt__new_buf(NULL, 0);
2007 return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
2008 }
2009
2010 static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
2011 {
2012 int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
2013 int has_subrs = 0, clear_stack;
2014 float s[48];
2015 stbtt__buf subr_stack[10], subrs = info->subrs, b;
2016 float f;
2017
2018 #define STBTT__CSERR(s) (0)
2019
2020
2021 b = stbtt__cff_index_get(info->charstrings, glyph_index);
2022 while (b.cursor < b.size) {
2023 i = 0;
2024 clear_stack = 1;
2025 b0 = stbtt__buf_get8(&b);
2026 switch (b0) {
2027
2028 case 0x13:
2029 case 0x14:
2030 if (in_header)
2031 maskbits += (sp / 2);
2032 in_header = 0;
2033 stbtt__buf_skip(&b, (maskbits + 7) / 8);
2034 break;
2035
2036 case 0x01:
2037 case 0x03:
2038 case 0x12:
2039 case 0x17:
2040 maskbits += (sp / 2);
2041 break;
2042
2043 case 0x15:
2044 in_header = 0;
2045 if (sp < 2) return STBTT__CSERR("rmoveto stack");
2046 stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
2047 break;
2048 case 0x04:
2049 in_header = 0;
2050 if (sp < 1) return STBTT__CSERR("vmoveto stack");
2051 stbtt__csctx_rmove_to(c, 0, s[sp-1]);
2052 break;
2053 case 0x16:
2054 in_header = 0;
2055 if (sp < 1) return STBTT__CSERR("hmoveto stack");
2056 stbtt__csctx_rmove_to(c, s[sp-1], 0);
2057 break;
2058
2059 case 0x05:
2060 if (sp < 2) return STBTT__CSERR("rlineto stack");
2061 for (; i + 1 < sp; i += 2)
2062 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2063 break;
2064
2065
2066
2067
2068 case 0x07:
2069 if (sp < 1) return STBTT__CSERR("vlineto stack");
2070 goto vlineto;
2071 case 0x06:
2072 if (sp < 1) return STBTT__CSERR("hlineto stack");
2073 for (;;) {
2074 if (i >= sp) break;
2075 stbtt__csctx_rline_to(c, s[i], 0);
2076 i++;
2077 vlineto:
2078 if (i >= sp) break;
2079 stbtt__csctx_rline_to(c, 0, s[i]);
2080 i++;
2081 }
2082 break;
2083
2084 case 0x1F:
2085 if (sp < 4) return STBTT__CSERR("hvcurveto stack");
2086 goto hvcurveto;
2087 case 0x1E:
2088 if (sp < 4) return STBTT__CSERR("vhcurveto stack");
2089 for (;;) {
2090 if (i + 3 >= sp) break;
2091 stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
2092 i += 4;
2093 hvcurveto:
2094 if (i + 3 >= sp) break;
2095 stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
2096 i += 4;
2097 }
2098 break;
2099
2100 case 0x08:
2101 if (sp < 6) return STBTT__CSERR("rcurveline stack");
2102 for (; i + 5 < sp; i += 6)
2103 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2104 break;
2105
2106 case 0x18:
2107 if (sp < 8) return STBTT__CSERR("rcurveline stack");
2108 for (; i + 5 < sp - 2; i += 6)
2109 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2110 if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
2111 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2112 break;
2113
2114 case 0x19:
2115 if (sp < 8) return STBTT__CSERR("rlinecurve stack");
2116 for (; i + 1 < sp - 6; i += 2)
2117 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2118 if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
2119 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2120 break;
2121
2122 case 0x1A:
2123 case 0x1B:
2124 if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
2125 f = 0.0;
2126 if (sp & 1) { f = s[i]; i++; }
2127 for (; i + 3 < sp; i += 4) {
2128 if (b0 == 0x1B)
2129 stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
2130 else
2131 stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
2132 f = 0.0;
2133 }
2134 break;
2135
2136 case 0x0A:
2137 if (!has_subrs) {
2138 if (info->fdselect.size)
2139 subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
2140 has_subrs = 1;
2141 }
2142
2143 case 0x1D:
2144 if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
2145 v = (int) s[--sp];
2146 if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
2147 subr_stack[subr_stack_height++] = b;
2148 b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
2149 if (b.size == 0) return STBTT__CSERR("subr not found");
2150 b.cursor = 0;
2151 clear_stack = 0;
2152 break;
2153
2154 case 0x0B:
2155 if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
2156 b = subr_stack[--subr_stack_height];
2157 clear_stack = 0;
2158 break;
2159
2160 case 0x0E:
2161 stbtt__csctx_close_shape(c);
2162 return 1;
2163
2164 case 0x0C: {
2165 float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
2166 float dx, dy;
2167 int b1 = stbtt__buf_get8(&b);
2168 switch (b1) {
2169
2170
2171 case 0x22:
2172 if (sp < 7) return STBTT__CSERR("hflex stack");
2173 dx1 = s[0];
2174 dx2 = s[1];
2175 dy2 = s[2];
2176 dx3 = s[3];
2177 dx4 = s[4];
2178 dx5 = s[5];
2179 dx6 = s[6];
2180 stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
2181 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
2182 break;
2183
2184 case 0x23:
2185 if (sp < 13) return STBTT__CSERR("flex stack");
2186 dx1 = s[0];
2187 dy1 = s[1];
2188 dx2 = s[2];
2189 dy2 = s[3];
2190 dx3 = s[4];
2191 dy3 = s[5];
2192 dx4 = s[6];
2193 dy4 = s[7];
2194 dx5 = s[8];
2195 dy5 = s[9];
2196 dx6 = s[10];
2197 dy6 = s[11];
2198
2199 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2200 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2201 break;
2202
2203 case 0x24:
2204 if (sp < 9) return STBTT__CSERR("hflex1 stack");
2205 dx1 = s[0];
2206 dy1 = s[1];
2207 dx2 = s[2];
2208 dy2 = s[3];
2209 dx3 = s[4];
2210 dx4 = s[5];
2211 dx5 = s[6];
2212 dy5 = s[7];
2213 dx6 = s[8];
2214 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
2215 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
2216 break;
2217
2218 case 0x25:
2219 if (sp < 11) return STBTT__CSERR("flex1 stack");
2220 dx1 = s[0];
2221 dy1 = s[1];
2222 dx2 = s[2];
2223 dy2 = s[3];
2224 dx3 = s[4];
2225 dy3 = s[5];
2226 dx4 = s[6];
2227 dy4 = s[7];
2228 dx5 = s[8];
2229 dy5 = s[9];
2230 dx6 = dy6 = s[10];
2231 dx = dx1+dx2+dx3+dx4+dx5;
2232 dy = dy1+dy2+dy3+dy4+dy5;
2233 if (STBTT_fabs(dx) > STBTT_fabs(dy))
2234 dy6 = -dy;
2235 else
2236 dx6 = -dx;
2237 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2238 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2239 break;
2240
2241 default:
2242 return STBTT__CSERR("unimplemented");
2243 }
2244 } break;
2245
2246 default:
2247 if (b0 != 255 && b0 != 28 && b0 < 32)
2248 return STBTT__CSERR("reserved operator");
2249
2250
2251 if (b0 == 255) {
2252 f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
2253 } else {
2254 stbtt__buf_skip(&b, -1);
2255 f = (float)(stbtt_int16)stbtt__cff_int(&b);
2256 }
2257 if (sp >= 48) return STBTT__CSERR("push stack overflow");
2258 s[sp++] = f;
2259 clear_stack = 0;
2260 break;
2261 }
2262 if (clear_stack) sp = 0;
2263 }
2264 return STBTT__CSERR("no endchar");
2265
2266 #undef STBTT__CSERR
2267 }
2268
2269 static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
2270 {
2271
2272 stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
2273 stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
2274 if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
2275 *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
2276 output_ctx.pvertices = *pvertices;
2277 if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
2278 STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
2279 return output_ctx.num_vertices;
2280 }
2281 }
2282 *pvertices = NULL;
2283 return 0;
2284 }
2285
2286 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
2287 {
2288 stbtt__csctx c = STBTT__CSCTX_INIT(1);
2289 int r = stbtt__run_charstring(info, glyph_index, &c);
2290 if (x0) *x0 = r ? c.min_x : 0;
2291 if (y0) *y0 = r ? c.min_y : 0;
2292 if (x1) *x1 = r ? c.max_x : 0;
2293 if (y1) *y1 = r ? c.max_y : 0;
2294 return r ? c.num_vertices : 0;
2295 }
2296
2297 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
2298 {
2299 if (!info->cff.size)
2300 return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
2301 else
2302 return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
2303 }
2304
2305 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
2306 {
2307 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
2308 if (glyph_index < numOfLongHorMetrics) {
2309 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
2310 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
2311 } else {
2312 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
2313 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
2314 }
2315 }
2316
2317 STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
2318 {
2319 stbtt_uint8 *data = info->data + info->kern;
2320
2321
2322 if (!info->kern)
2323 return 0;
2324 if (ttUSHORT(data+2) < 1)
2325 return 0;
2326 if (ttUSHORT(data+8) != 1)
2327 return 0;
2328
2329 return ttUSHORT(data+10);
2330 }
2331
2332 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
2333 {
2334 stbtt_uint8 *data = info->data + info->kern;
2335 int k, length;
2336
2337
2338 if (!info->kern)
2339 return 0;
2340 if (ttUSHORT(data+2) < 1)
2341 return 0;
2342 if (ttUSHORT(data+8) != 1)
2343 return 0;
2344
2345 length = ttUSHORT(data+10);
2346 if (table_length < length)
2347 length = table_length;
2348
2349 for (k = 0; k < length; k++)
2350 {
2351 table[k].glyph1 = ttUSHORT(data+18+(k*6));
2352 table[k].glyph2 = ttUSHORT(data+20+(k*6));
2353 table[k].advance = ttSHORT(data+22+(k*6));
2354 }
2355
2356 return length;
2357 }
2358
2359 static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2360 {
2361 stbtt_uint8 *data = info->data + info->kern;
2362 stbtt_uint32 needle, straw;
2363 int l, r, m;
2364
2365
2366 if (!info->kern)
2367 return 0;
2368 if (ttUSHORT(data+2) < 1)
2369 return 0;
2370 if (ttUSHORT(data+8) != 1)
2371 return 0;
2372
2373 l = 0;
2374 r = ttUSHORT(data+10) - 1;
2375 needle = glyph1 << 16 | glyph2;
2376 while (l <= r) {
2377 m = (l + r) >> 1;
2378 straw = ttULONG(data+18+(m*6));
2379 if (needle < straw)
2380 r = m - 1;
2381 else if (needle > straw)
2382 l = m + 1;
2383 else
2384 return ttSHORT(data+22+(m*6));
2385 }
2386 return 0;
2387 }
2388
2389 static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
2390 {
2391 stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2392 switch (coverageFormat) {
2393 case 1: {
2394 stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2395
2396
2397 stbtt_int32 l=0, r=glyphCount-1, m;
2398 int straw, needle=glyph;
2399 while (l <= r) {
2400 stbtt_uint8 *glyphArray = coverageTable + 4;
2401 stbtt_uint16 glyphID;
2402 m = (l + r) >> 1;
2403 glyphID = ttUSHORT(glyphArray + 2 * m);
2404 straw = glyphID;
2405 if (needle < straw)
2406 r = m - 1;
2407 else if (needle > straw)
2408 l = m + 1;
2409 else {
2410 return m;
2411 }
2412 }
2413 break;
2414 }
2415
2416 case 2: {
2417 stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2418 stbtt_uint8 *rangeArray = coverageTable + 4;
2419
2420
2421 stbtt_int32 l=0, r=rangeCount-1, m;
2422 int strawStart, strawEnd, needle=glyph;
2423 while (l <= r) {
2424 stbtt_uint8 *rangeRecord;
2425 m = (l + r) >> 1;
2426 rangeRecord = rangeArray + 6 * m;
2427 strawStart = ttUSHORT(rangeRecord);
2428 strawEnd = ttUSHORT(rangeRecord + 2);
2429 if (needle < strawStart)
2430 r = m - 1;
2431 else if (needle > strawEnd)
2432 l = m + 1;
2433 else {
2434 stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2435 return startCoverageIndex + glyph - strawStart;
2436 }
2437 }
2438 break;
2439 }
2440
2441 default: return -1;
2442 }
2443
2444 return -1;
2445 }
2446
2447 static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
2448 {
2449 stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2450 switch (classDefFormat)
2451 {
2452 case 1: {
2453 stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2454 stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2455 stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
2456
2457 if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2458 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2459 break;
2460 }
2461
2462 case 2: {
2463 stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2464 stbtt_uint8 *classRangeRecords = classDefTable + 4;
2465
2466
2467 stbtt_int32 l=0, r=classRangeCount-1, m;
2468 int strawStart, strawEnd, needle=glyph;
2469 while (l <= r) {
2470 stbtt_uint8 *classRangeRecord;
2471 m = (l + r) >> 1;
2472 classRangeRecord = classRangeRecords + 6 * m;
2473 strawStart = ttUSHORT(classRangeRecord);
2474 strawEnd = ttUSHORT(classRangeRecord + 2);
2475 if (needle < strawStart)
2476 r = m - 1;
2477 else if (needle > strawEnd)
2478 l = m + 1;
2479 else
2480 return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2481 }
2482 break;
2483 }
2484
2485 default:
2486 return -1;
2487 }
2488
2489
2490 return 0;
2491 }
2492
2493
2494 #define STBTT_GPOS_TODO_assert(x)
2495
2496 static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2497 {
2498 stbtt_uint16 lookupListOffset;
2499 stbtt_uint8 *lookupList;
2500 stbtt_uint16 lookupCount;
2501 stbtt_uint8 *data;
2502 stbtt_int32 i, sti;
2503
2504 if (!info->gpos) return 0;
2505
2506 data = info->data + info->gpos;
2507
2508 if (ttUSHORT(data+0) != 1) return 0;
2509 if (ttUSHORT(data+2) != 0) return 0;
2510
2511 lookupListOffset = ttUSHORT(data+8);
2512 lookupList = data + lookupListOffset;
2513 lookupCount = ttUSHORT(lookupList);
2514
2515 for (i=0; i<lookupCount; ++i) {
2516 stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2517 stbtt_uint8 *lookupTable = lookupList + lookupOffset;
2518
2519 stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2520 stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2521 stbtt_uint8 *subTableOffsets = lookupTable + 6;
2522 if (lookupType != 2)
2523 continue;
2524
2525 for (sti=0; sti<subTableCount; sti++) {
2526 stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2527 stbtt_uint8 *table = lookupTable + subtableOffset;
2528 stbtt_uint16 posFormat = ttUSHORT(table);
2529 stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2530 stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2531 if (coverageIndex == -1) continue;
2532
2533 switch (posFormat) {
2534 case 1: {
2535 stbtt_int32 l, r, m;
2536 int straw, needle;
2537 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2538 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2539 if (valueFormat1 == 4 && valueFormat2 == 0) {
2540 stbtt_int32 valueRecordPairSizeInBytes = 2;
2541 stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2542 stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2543 stbtt_uint8 *pairValueTable = table + pairPosOffset;
2544 stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2545 stbtt_uint8 *pairValueArray = pairValueTable + 2;
2546
2547 if (coverageIndex >= pairSetCount) return 0;
2548
2549 needle=glyph2;
2550 r=pairValueCount-1;
2551 l=0;
2552
2553
2554 while (l <= r) {
2555 stbtt_uint16 secondGlyph;
2556 stbtt_uint8 *pairValue;
2557 m = (l + r) >> 1;
2558 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2559 secondGlyph = ttUSHORT(pairValue);
2560 straw = secondGlyph;
2561 if (needle < straw)
2562 r = m - 1;
2563 else if (needle > straw)
2564 l = m + 1;
2565 else {
2566 stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2567 return xAdvance;
2568 }
2569 }
2570 } else
2571 return 0;
2572 break;
2573 }
2574
2575 case 2: {
2576 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2577 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2578 if (valueFormat1 == 4 && valueFormat2 == 0) {
2579 stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2580 stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2581 int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2582 int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2583
2584 stbtt_uint16 class1Count = ttUSHORT(table + 12);
2585 stbtt_uint16 class2Count = ttUSHORT(table + 14);
2586 stbtt_uint8 *class1Records, *class2Records;
2587 stbtt_int16 xAdvance;
2588
2589 if (glyph1class < 0 || glyph1class >= class1Count) return 0;
2590 if (glyph2class < 0 || glyph2class >= class2Count) return 0;
2591
2592 class1Records = table + 16;
2593 class2Records = class1Records + 2 * (glyph1class * class2Count);
2594 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2595 return xAdvance;
2596 } else
2597 return 0;
2598 break;
2599 }
2600
2601 default:
2602 return 0;
2603 }
2604 }
2605 }
2606
2607 return 0;
2608 }
2609
2610 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
2611 {
2612 int xAdvance = 0;
2613
2614 if (info->gpos)
2615 xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
2616 else if (info->kern)
2617 xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
2618
2619 return xAdvance;
2620 }
2621
2622 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
2623 {
2624 if (!info->kern && !info->gpos)
2625 return 0;
2626 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
2627 }
2628
2629 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
2630 {
2631 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
2632 }
2633
2634 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
2635 {
2636 if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
2637 if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
2638 if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
2639 }
2640
2641 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
2642 {
2643 int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
2644 if (!tab)
2645 return 0;
2646 if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
2647 if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
2648 if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
2649 return 1;
2650 }
2651
2652 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
2653 {
2654 *x0 = ttSHORT(info->data + info->head + 36);
2655 *y0 = ttSHORT(info->data + info->head + 38);
2656 *x1 = ttSHORT(info->data + info->head + 40);
2657 *y1 = ttSHORT(info->data + info->head + 42);
2658 }
2659
2660 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
2661 {
2662 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
2663 return (float) height / fheight;
2664 }
2665
2666 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
2667 {
2668 int unitsPerEm = ttUSHORT(info->data + info->head + 18);
2669 return pixels / unitsPerEm;
2670 }
2671
2672 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
2673 {
2674 STBTT_free(v, info->userdata);
2675 }
2676
2677 STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
2678 {
2679 int i;
2680 stbtt_uint8 *data = info->data;
2681 stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
2682
2683 int numEntries = ttUSHORT(svg_doc_list);
2684 stbtt_uint8 *svg_docs = svg_doc_list + 2;
2685
2686 for(i=0; i<numEntries; i++) {
2687 stbtt_uint8 *svg_doc = svg_docs + (12 * i);
2688 if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
2689 return svg_doc;
2690 }
2691 return 0;
2692 }
2693
2694 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
2695 {
2696 stbtt_uint8 *data = info->data;
2697 stbtt_uint8 *svg_doc;
2698
2699 if (info->svg == 0)
2700 return 0;
2701
2702 svg_doc = stbtt_FindSVGDoc(info, gl);
2703 if (svg_doc != NULL) {
2704 *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
2705 return ttULONG(svg_doc + 8);
2706 } else {
2707 return 0;
2708 }
2709 }
2710
2711 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
2712 {
2713 return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
2714 }
2715
2716
2717
2718
2719
2720
2721 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
2722 {
2723 int x0=0,y0=0,x1,y1;
2724 if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
2725
2726 if (ix0) *ix0 = 0;
2727 if (iy0) *iy0 = 0;
2728 if (ix1) *ix1 = 0;
2729 if (iy1) *iy1 = 0;
2730 } else {
2731
2732 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
2733 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
2734 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
2735 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
2736 }
2737 }
2738
2739 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
2740 {
2741 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
2742 }
2743
2744 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
2745 {
2746 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
2747 }
2748
2749 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
2750 {
2751 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
2752 }
2753
2754
2755
2756
2757
2758 typedef struct stbtt__hheap_chunk
2759 {
2760 struct stbtt__hheap_chunk *next;
2761 } stbtt__hheap_chunk;
2762
2763 typedef struct stbtt__hheap
2764 {
2765 struct stbtt__hheap_chunk *head;
2766 void *first_free;
2767 int num_remaining_in_head_chunk;
2768 } stbtt__hheap;
2769
2770 static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
2771 {
2772 if (hh->first_free) {
2773 void *p = hh->first_free;
2774 hh->first_free = * (void **) p;
2775 return p;
2776 } else {
2777 if (hh->num_remaining_in_head_chunk == 0) {
2778 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
2779 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
2780 if (c == NULL)
2781 return NULL;
2782 c->next = hh->head;
2783 hh->head = c;
2784 hh->num_remaining_in_head_chunk = count;
2785 }
2786 --hh->num_remaining_in_head_chunk;
2787 return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
2788 }
2789 }
2790
2791 static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
2792 {
2793 *(void **) p = hh->first_free;
2794 hh->first_free = p;
2795 }
2796
2797 static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
2798 {
2799 stbtt__hheap_chunk *c = hh->head;
2800 while (c) {
2801 stbtt__hheap_chunk *n = c->next;
2802 STBTT_free(c, userdata);
2803 c = n;
2804 }
2805 }
2806
2807 typedef struct stbtt__edge {
2808 float x0,y0, x1,y1;
2809 int invert;
2810 } stbtt__edge;
2811
2812
2813 typedef struct stbtt__active_edge
2814 {
2815 struct stbtt__active_edge *next;
2816 #if STBTT_RASTERIZER_VERSION==1
2817 int x,dx;
2818 float ey;
2819 int direction;
2820 #elif STBTT_RASTERIZER_VERSION==2
2821 float fx,fdx,fdy;
2822 float direction;
2823 float sy;
2824 float ey;
2825 #else
2826 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2827 #endif
2828 } stbtt__active_edge;
2829
2830 #if STBTT_RASTERIZER_VERSION == 1
2831 #define STBTT_FIXSHIFT 10
2832 #define STBTT_FIX (1 << STBTT_FIXSHIFT)
2833 #define STBTT_FIXMASK (STBTT_FIX-1)
2834
2835 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
2836 {
2837 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2838 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2839 STBTT_assert(z != NULL);
2840 if (!z) return z;
2841
2842
2843 if (dxdy < 0)
2844 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
2845 else
2846 z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
2847
2848 z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0));
2849 z->x -= off_x * STBTT_FIX;
2850
2851 z->ey = e->y1;
2852 z->next = 0;
2853 z->direction = e->invert ? 1 : -1;
2854 return z;
2855 }
2856 #elif STBTT_RASTERIZER_VERSION == 2
2857 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
2858 {
2859 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
2860 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2861 STBTT_assert(z != NULL);
2862
2863 if (!z) return z;
2864 z->fdx = dxdy;
2865 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
2866 z->fx = e->x0 + dxdy * (start_point - e->y0);
2867 z->fx -= off_x;
2868 z->direction = e->invert ? 1.0f : -1.0f;
2869 z->sy = e->y0;
2870 z->ey = e->y1;
2871 z->next = 0;
2872 return z;
2873 }
2874 #else
2875 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2876 #endif
2877
2878 #if STBTT_RASTERIZER_VERSION == 1
2879
2880
2881
2882 static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
2883 {
2884
2885 int x0=0, w=0;
2886
2887 while (e) {
2888 if (w == 0) {
2889
2890 x0 = e->x; w += e->direction;
2891 } else {
2892 int x1 = e->x; w += e->direction;
2893
2894 if (w == 0) {
2895 int i = x0 >> STBTT_FIXSHIFT;
2896 int j = x1 >> STBTT_FIXSHIFT;
2897
2898 if (i < len && j >= 0) {
2899 if (i == j) {
2900
2901 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
2902 } else {
2903 if (i >= 0)
2904 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
2905 else
2906 i = -1;
2907
2908 if (j < len)
2909 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
2910 else
2911 j = len;
2912
2913 for (++i; i < j; ++i)
2914 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
2915 }
2916 }
2917 }
2918 }
2919
2920 e = e->next;
2921 }
2922 }
2923
2924 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
2925 {
2926 stbtt__hheap hh = { 0, 0, 0 };
2927 stbtt__active_edge *active = NULL;
2928 int y,j=0;
2929 int max_weight = (255 / vsubsample);
2930 int s;
2931 unsigned char scanline_data[512], *scanline;
2932
2933 if (result->w > 512)
2934 scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
2935 else
2936 scanline = scanline_data;
2937
2938 y = off_y * vsubsample;
2939 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
2940
2941 while (j < result->h) {
2942 STBTT_memset(scanline, 0, result->w);
2943 for (s=0; s < vsubsample; ++s) {
2944
2945 float scan_y = y + 0.5f;
2946 stbtt__active_edge **step = &active;
2947
2948
2949
2950 while (*step) {
2951 stbtt__active_edge * z = *step;
2952 if (z->ey <= scan_y) {
2953 *step = z->next;
2954 STBTT_assert(z->direction);
2955 z->direction = 0;
2956 stbtt__hheap_free(&hh, z);
2957 } else {
2958 z->x += z->dx;
2959 step = &((*step)->next);
2960 }
2961 }
2962
2963
2964 for(;;) {
2965 int changed=0;
2966 step = &active;
2967 while (*step && (*step)->next) {
2968 if ((*step)->x > (*step)->next->x) {
2969 stbtt__active_edge *t = *step;
2970 stbtt__active_edge *q = t->next;
2971
2972 t->next = q->next;
2973 q->next = t;
2974 *step = q;
2975 changed = 1;
2976 }
2977 step = &(*step)->next;
2978 }
2979 if (!changed) break;
2980 }
2981
2982
2983 while (e->y0 <= scan_y) {
2984 if (e->y1 > scan_y) {
2985 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
2986 if (z != NULL) {
2987
2988 if (active == NULL)
2989 active = z;
2990 else if (z->x < active->x) {
2991
2992 z->next = active;
2993 active = z;
2994 } else {
2995
2996 stbtt__active_edge *p = active;
2997 while (p->next && p->next->x < z->x)
2998 p = p->next;
2999
3000 z->next = p->next;
3001 p->next = z;
3002 }
3003 }
3004 }
3005 ++e;
3006 }
3007
3008
3009 if (active)
3010 stbtt__fill_active_edges(scanline, result->w, active, max_weight);
3011
3012 ++y;
3013 }
3014 STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
3015 ++j;
3016 }
3017
3018 stbtt__hheap_cleanup(&hh, userdata);
3019
3020 if (scanline != scanline_data)
3021 STBTT_free(scanline, userdata);
3022 }
3023
3024 #elif STBTT_RASTERIZER_VERSION == 2
3025
3026
3027
3028 static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
3029 {
3030 if (y0 == y1) return;
3031 STBTT_assert(y0 < y1);
3032 STBTT_assert(e->sy <= e->ey);
3033 if (y0 > e->ey) return;
3034 if (y1 < e->sy) return;
3035 if (y0 < e->sy) {
3036 x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
3037 y0 = e->sy;
3038 }
3039 if (y1 > e->ey) {
3040 x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
3041 y1 = e->ey;
3042 }
3043
3044 if (x0 == x)
3045 STBTT_assert(x1 <= x+1);
3046 else if (x0 == x+1)
3047 STBTT_assert(x1 >= x);
3048 else if (x0 <= x)
3049 STBTT_assert(x1 <= x);
3050 else if (x0 >= x+1)
3051 STBTT_assert(x1 >= x+1);
3052 else
3053 STBTT_assert(x1 >= x && x1 <= x+1);
3054
3055 if (x0 <= x && x1 <= x)
3056 scanline[x] += e->direction * (y1-y0);
3057 else if (x0 >= x+1 && x1 >= x+1)
3058 ;
3059 else {
3060 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
3061 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2);
3062 }
3063 }
3064
3065 static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
3066 {
3067 STBTT_assert(top_width >= 0);
3068 STBTT_assert(bottom_width >= 0);
3069 return (top_width + bottom_width) / 2.0f * height;
3070 }
3071
3072 static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
3073 {
3074 return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
3075 }
3076
3077 static float stbtt__sized_triangle_area(float height, float width)
3078 {
3079 return height * width / 2;
3080 }
3081
3082 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
3083 {
3084 float y_bottom = y_top+1;
3085
3086 while (e) {
3087
3088
3089
3090 STBTT_assert(e->ey >= y_top);
3091
3092 if (e->fdx == 0) {
3093 float x0 = e->fx;
3094 if (x0 < len) {
3095 if (x0 >= 0) {
3096 stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
3097 stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
3098 } else {
3099 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
3100 }
3101 }
3102 } else {
3103 float x0 = e->fx;
3104 float dx = e->fdx;
3105 float xb = x0 + dx;
3106 float x_top, x_bottom;
3107 float sy0,sy1;
3108 float dy = e->fdy;
3109 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
3110
3111
3112
3113
3114 if (e->sy > y_top) {
3115 x_top = x0 + dx * (e->sy - y_top);
3116 sy0 = e->sy;
3117 } else {
3118 x_top = x0;
3119 sy0 = y_top;
3120 }
3121 if (e->ey < y_bottom) {
3122 x_bottom = x0 + dx * (e->ey - y_top);
3123 sy1 = e->ey;
3124 } else {
3125 x_bottom = xb;
3126 sy1 = y_bottom;
3127 }
3128
3129 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
3130
3131
3132 if ((int) x_top == (int) x_bottom) {
3133 float height;
3134
3135 int x = (int) x_top;
3136 height = (sy1 - sy0) * e->direction;
3137 STBTT_assert(x >= 0 && x < len);
3138 scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
3139 scanline_fill[x] += height;
3140 } else {
3141 int x,x1,x2;
3142 float y_crossing, y_final, step, sign, area;
3143
3144 if (x_top > x_bottom) {
3145
3146 float t;
3147 sy0 = y_bottom - (sy0 - y_top);
3148 sy1 = y_bottom - (sy1 - y_top);
3149 t = sy0, sy0 = sy1, sy1 = t;
3150 t = x_bottom, x_bottom = x_top, x_top = t;
3151 dx = -dx;
3152 dy = -dy;
3153 t = x0, x0 = xb, xb = t;
3154 }
3155 STBTT_assert(dy >= 0);
3156 STBTT_assert(dx >= 0);
3157
3158 x1 = (int) x_top;
3159 x2 = (int) x_bottom;
3160
3161 y_crossing = y_top + dy * (x1+1 - x0);
3162
3163
3164 y_final = y_top + dy * (x2 - x0);
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185 if (y_crossing > y_bottom)
3186 y_crossing = y_bottom;
3187
3188 sign = e->direction;
3189
3190
3191 area = sign * (y_crossing-sy0);
3192
3193
3194 scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
3195
3196
3197 if (y_final > y_bottom) {
3198 y_final = y_bottom;
3199 dy = (y_final - y_crossing ) / (x2 - (x1+1));
3200 }
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212 step = sign * dy * 1;
3213
3214
3215
3216 for (x = x1+1; x < x2; ++x) {
3217 scanline[x] += area + step/2;
3218 area += step;
3219 }
3220 STBTT_assert(STBTT_fabs(area) <= 1.01f);
3221 STBTT_assert(sy1 > y_final-0.01f);
3222
3223
3224
3225 scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
3226
3227
3228 scanline_fill[x2] += sign * (sy1-sy0);
3229 }
3230 } else {
3231
3232
3233
3234
3235
3236
3237
3238 int x;
3239 for (x=0; x < len; ++x) {
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254 float y0 = y_top;
3255 float x1 = (float) (x);
3256 float x2 = (float) (x+1);
3257 float x3 = xb;
3258 float y3 = y_bottom;
3259
3260
3261
3262
3263 float y1 = (x - x0) / dx + y_top;
3264 float y2 = (x+1 - x0) / dx + y_top;
3265
3266 if (x0 < x1 && x3 > x2) {
3267 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3268 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
3269 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3270 } else if (x3 < x1 && x0 > x2) {
3271 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3272 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
3273 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3274 } else if (x0 < x1 && x3 > x1) {
3275 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3276 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3277 } else if (x3 < x1 && x0 > x1) {
3278 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3279 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3280 } else if (x0 < x2 && x3 > x2) {
3281 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3282 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3283 } else if (x3 < x2 && x0 > x2) {
3284 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3285 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3286 } else {
3287 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
3288 }
3289 }
3290 }
3291 }
3292 e = e->next;
3293 }
3294 }
3295
3296
3297 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
3298 {
3299 stbtt__hheap hh = { 0, 0, 0 };
3300 stbtt__active_edge *active = NULL;
3301 int y,j=0, i;
3302 float scanline_data[129], *scanline, *scanline2;
3303
3304 STBTT__NOTUSED(vsubsample);
3305
3306 if (result->w > 64)
3307 scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
3308 else
3309 scanline = scanline_data;
3310
3311 scanline2 = scanline + result->w;
3312
3313 y = off_y;
3314 e[n].y0 = (float) (off_y + result->h) + 1;
3315
3316 while (j < result->h) {
3317
3318 float scan_y_top = y + 0.0f;
3319 float scan_y_bottom = y + 1.0f;
3320 stbtt__active_edge **step = &active;
3321
3322 STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
3323 STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
3324
3325
3326
3327 while (*step) {
3328 stbtt__active_edge * z = *step;
3329 if (z->ey <= scan_y_top) {
3330 *step = z->next;
3331 STBTT_assert(z->direction);
3332 z->direction = 0;
3333 stbtt__hheap_free(&hh, z);
3334 } else {
3335 step = &((*step)->next);
3336 }
3337 }
3338
3339
3340 while (e->y0 <= scan_y_bottom) {
3341 if (e->y0 != e->y1) {
3342 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
3343 if (z != NULL) {
3344 if (j == 0 && off_y != 0) {
3345 if (z->ey < scan_y_top) {
3346
3347 z->ey = scan_y_top;
3348 }
3349 }
3350 STBTT_assert(z->ey >= scan_y_top);
3351
3352 z->next = active;
3353 active = z;
3354 }
3355 }
3356 ++e;
3357 }
3358
3359
3360 if (active)
3361 stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
3362
3363 {
3364 float sum = 0;
3365 for (i=0; i < result->w; ++i) {
3366 float k;
3367 int m;
3368 sum += scanline2[i];
3369 k = scanline[i] + sum;
3370 k = (float) STBTT_fabs(k)*255 + 0.5f;
3371 m = (int) k;
3372 if (m > 255) m = 255;
3373 result->pixels[j*result->stride + i] = (unsigned char) m;
3374 }
3375 }
3376
3377 step = &active;
3378 while (*step) {
3379 stbtt__active_edge *z = *step;
3380 z->fx += z->fdx;
3381 step = &((*step)->next);
3382 }
3383
3384 ++y;
3385 ++j;
3386 }
3387
3388 stbtt__hheap_cleanup(&hh, userdata);
3389
3390 if (scanline != scanline_data)
3391 STBTT_free(scanline, userdata);
3392 }
3393 #else
3394 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3395 #endif
3396
3397 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
3398
3399 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
3400 {
3401 int i,j;
3402 for (i=1; i < n; ++i) {
3403 stbtt__edge t = p[i], *a = &t;
3404 j = i;
3405 while (j > 0) {
3406 stbtt__edge *b = &p[j-1];
3407 int c = STBTT__COMPARE(a,b);
3408 if (!c) break;
3409 p[j] = p[j-1];
3410 --j;
3411 }
3412 if (i != j)
3413 p[j] = t;
3414 }
3415 }
3416
3417 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
3418 {
3419
3420 while (n > 12) {
3421 stbtt__edge t;
3422 int c01,c12,c,m,i,j;
3423
3424
3425 m = n >> 1;
3426 c01 = STBTT__COMPARE(&p[0],&p[m]);
3427 c12 = STBTT__COMPARE(&p[m],&p[n-1]);
3428
3429 if (c01 != c12) {
3430
3431 int z;
3432 c = STBTT__COMPARE(&p[0],&p[n-1]);
3433
3434
3435 z = (c == c12) ? 0 : n-1;
3436 t = p[z];
3437 p[z] = p[m];
3438 p[m] = t;
3439 }
3440
3441
3442 t = p[0];
3443 p[0] = p[m];
3444 p[m] = t;
3445
3446
3447 i=1;
3448 j=n-1;
3449 for(;;) {
3450
3451
3452 for (;;++i) {
3453 if (!STBTT__COMPARE(&p[i], &p[0])) break;
3454 }
3455 for (;;--j) {
3456 if (!STBTT__COMPARE(&p[0], &p[j])) break;
3457 }
3458
3459 if (i >= j) break;
3460 t = p[i];
3461 p[i] = p[j];
3462 p[j] = t;
3463
3464 ++i;
3465 --j;
3466 }
3467
3468 if (j < (n-i)) {
3469 stbtt__sort_edges_quicksort(p,j);
3470 p = p+i;
3471 n = n-i;
3472 } else {
3473 stbtt__sort_edges_quicksort(p+i, n-i);
3474 n = j;
3475 }
3476 }
3477 }
3478
3479 static void stbtt__sort_edges(stbtt__edge *p, int n)
3480 {
3481 stbtt__sort_edges_quicksort(p, n);
3482 stbtt__sort_edges_ins_sort(p, n);
3483 }
3484
3485 typedef struct
3486 {
3487 float x,y;
3488 } stbtt__point;
3489
3490 static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
3491 {
3492 float y_scale_inv = invert ? -scale_y : scale_y;
3493 stbtt__edge *e;
3494 int n,i,j,k,m;
3495 #if STBTT_RASTERIZER_VERSION == 1
3496 int vsubsample = result->h < 8 ? 15 : 5;
3497 #elif STBTT_RASTERIZER_VERSION == 2
3498 int vsubsample = 1;
3499 #else
3500 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3501 #endif
3502
3503
3504
3505 n = 0;
3506 for (i=0; i < windings; ++i)
3507 n += wcount[i];
3508
3509 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata);
3510 if (e == 0) return;
3511 n = 0;
3512
3513 m=0;
3514 for (i=0; i < windings; ++i) {
3515 stbtt__point *p = pts + m;
3516 m += wcount[i];
3517 j = wcount[i]-1;
3518 for (k=0; k < wcount[i]; j=k++) {
3519 int a=k,b=j;
3520
3521 if (p[j].y == p[k].y)
3522 continue;
3523
3524 e[n].invert = 0;
3525 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
3526 e[n].invert = 1;
3527 a=j,b=k;
3528 }
3529 e[n].x0 = p[a].x * scale_x + shift_x;
3530 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
3531 e[n].x1 = p[b].x * scale_x + shift_x;
3532 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
3533 ++n;
3534 }
3535 }
3536
3537
3538
3539 stbtt__sort_edges(e, n);
3540
3541
3542 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
3543
3544 STBTT_free(e, userdata);
3545 }
3546
3547 static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
3548 {
3549 if (!points) return;
3550 points[n].x = x;
3551 points[n].y = y;
3552 }
3553
3554
3555 static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
3556 {
3557
3558 float mx = (x0 + 2*x1 + x2)/4;
3559 float my = (y0 + 2*y1 + y2)/4;
3560
3561 float dx = (x0+x2)/2 - mx;
3562 float dy = (y0+y2)/2 - my;
3563 if (n > 16)
3564 return 1;
3565 if (dx*dx+dy*dy > objspace_flatness_squared) {
3566 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
3567 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
3568 } else {
3569 stbtt__add_point(points, *num_points,x2,y2);
3570 *num_points = *num_points+1;
3571 }
3572 return 1;
3573 }
3574
3575 static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
3576 {
3577
3578 float dx0 = x1-x0;
3579 float dy0 = y1-y0;
3580 float dx1 = x2-x1;
3581 float dy1 = y2-y1;
3582 float dx2 = x3-x2;
3583 float dy2 = y3-y2;
3584 float dx = x3-x0;
3585 float dy = y3-y0;
3586 float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
3587 float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
3588 float flatness_squared = longlen*longlen-shortlen*shortlen;
3589
3590 if (n > 16)
3591 return;
3592
3593 if (flatness_squared > objspace_flatness_squared) {
3594 float x01 = (x0+x1)/2;
3595 float y01 = (y0+y1)/2;
3596 float x12 = (x1+x2)/2;
3597 float y12 = (y1+y2)/2;
3598 float x23 = (x2+x3)/2;
3599 float y23 = (y2+y3)/2;
3600
3601 float xa = (x01+x12)/2;
3602 float ya = (y01+y12)/2;
3603 float xb = (x12+x23)/2;
3604 float yb = (y12+y23)/2;
3605
3606 float mx = (xa+xb)/2;
3607 float my = (ya+yb)/2;
3608
3609 stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
3610 stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
3611 } else {
3612 stbtt__add_point(points, *num_points,x3,y3);
3613 *num_points = *num_points+1;
3614 }
3615 }
3616
3617
3618 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
3619 {
3620 stbtt__point *points=0;
3621 int num_points=0;
3622
3623 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
3624 int i,n=0,start=0, pass;
3625
3626
3627 for (i=0; i < num_verts; ++i)
3628 if (vertices[i].type == STBTT_vmove)
3629 ++n;
3630
3631 *num_contours = n;
3632 if (n == 0) return 0;
3633
3634 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
3635
3636 if (*contour_lengths == 0) {
3637 *num_contours = 0;
3638 return 0;
3639 }
3640
3641
3642 for (pass=0; pass < 2; ++pass) {
3643 float x=0,y=0;
3644 if (pass == 1) {
3645 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
3646 if (points == NULL) goto error;
3647 }
3648 num_points = 0;
3649 n= -1;
3650 for (i=0; i < num_verts; ++i) {
3651 switch (vertices[i].type) {
3652 case STBTT_vmove:
3653
3654 if (n >= 0)
3655 (*contour_lengths)[n] = num_points - start;
3656 ++n;
3657 start = num_points;
3658
3659 x = vertices[i].x, y = vertices[i].y;
3660 stbtt__add_point(points, num_points++, x,y);
3661 break;
3662 case STBTT_vline:
3663 x = vertices[i].x, y = vertices[i].y;
3664 stbtt__add_point(points, num_points++, x, y);
3665 break;
3666 case STBTT_vcurve:
3667 stbtt__tesselate_curve(points, &num_points, x,y,
3668 vertices[i].cx, vertices[i].cy,
3669 vertices[i].x, vertices[i].y,
3670 objspace_flatness_squared, 0);
3671 x = vertices[i].x, y = vertices[i].y;
3672 break;
3673 case STBTT_vcubic:
3674 stbtt__tesselate_cubic(points, &num_points, x,y,
3675 vertices[i].cx, vertices[i].cy,
3676 vertices[i].cx1, vertices[i].cy1,
3677 vertices[i].x, vertices[i].y,
3678 objspace_flatness_squared, 0);
3679 x = vertices[i].x, y = vertices[i].y;
3680 break;
3681 }
3682 }
3683 (*contour_lengths)[n] = num_points - start;
3684 }
3685
3686 return points;
3687 error:
3688 STBTT_free(points, userdata);
3689 STBTT_free(*contour_lengths, userdata);
3690 *contour_lengths = 0;
3691 *num_contours = 0;
3692 return NULL;
3693 }
3694
3695 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
3696 {
3697 float scale = scale_x > scale_y ? scale_y : scale_x;
3698 int winding_count = 0;
3699 int *winding_lengths = NULL;
3700 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
3701 if (windings) {
3702 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
3703 STBTT_free(winding_lengths, userdata);
3704 STBTT_free(windings, userdata);
3705 }
3706 }
3707
3708 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
3709 {
3710 STBTT_free(bitmap, userdata);
3711 }
3712
3713 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
3714 {
3715 int ix0,iy0,ix1,iy1;
3716 stbtt__bitmap gbm;
3717 stbtt_vertex *vertices;
3718 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3719
3720 if (scale_x == 0) scale_x = scale_y;
3721 if (scale_y == 0) {
3722 if (scale_x == 0) {
3723 STBTT_free(vertices, info->userdata);
3724 return NULL;
3725 }
3726 scale_y = scale_x;
3727 }
3728
3729 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
3730
3731
3732 gbm.w = (ix1 - ix0);
3733 gbm.h = (iy1 - iy0);
3734 gbm.pixels = NULL;
3735
3736 if (width ) *width = gbm.w;
3737 if (height) *height = gbm.h;
3738 if (xoff ) *xoff = ix0;
3739 if (yoff ) *yoff = iy0;
3740
3741 if (gbm.w && gbm.h) {
3742 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
3743 if (gbm.pixels) {
3744 gbm.stride = gbm.w;
3745
3746 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
3747 }
3748 }
3749 STBTT_free(vertices, info->userdata);
3750 return gbm.pixels;
3751 }
3752
3753 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
3754 {
3755 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
3756 }
3757
3758 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
3759 {
3760 int ix0,iy0;
3761 stbtt_vertex *vertices;
3762 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
3763 stbtt__bitmap gbm;
3764
3765 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
3766 gbm.pixels = output;
3767 gbm.w = out_w;
3768 gbm.h = out_h;
3769 gbm.stride = out_stride;
3770
3771 if (gbm.w && gbm.h)
3772 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
3773
3774 STBTT_free(vertices, info->userdata);
3775 }
3776
3777 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
3778 {
3779 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
3780 }
3781
3782 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
3783 {
3784 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
3785 }
3786
3787 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
3788 {
3789 stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
3790 }
3791
3792 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
3793 {
3794 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
3795 }
3796
3797 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
3798 {
3799 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
3800 }
3801
3802 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
3803 {
3804 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
3805 }
3806
3807
3808
3809
3810
3811
3812
3813 static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset,
3814 float pixel_height,
3815 unsigned char *pixels, int pw, int ph,
3816 int first_char, int num_chars,
3817 stbtt_bakedchar *chardata)
3818 {
3819 float scale;
3820 int x,y,bottom_y, i;
3821 stbtt_fontinfo f;
3822 f.userdata = NULL;
3823 if (!stbtt_InitFont(&f, data, offset))
3824 return -1;
3825 STBTT_memset(pixels, 0, pw*ph);
3826 x=y=1;
3827 bottom_y = 1;
3828
3829 scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
3830
3831 for (i=0; i < num_chars; ++i) {
3832 int advance, lsb, x0,y0,x1,y1,gw,gh;
3833 int g = stbtt_FindGlyphIndex(&f, first_char + i);
3834 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
3835 stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
3836 gw = x1-x0;
3837 gh = y1-y0;
3838 if (x + gw + 1 >= pw)
3839 y = bottom_y, x = 1;
3840 if (y + gh + 1 >= ph)
3841 return -i;
3842 STBTT_assert(x+gw < pw);
3843 STBTT_assert(y+gh < ph);
3844 stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
3845 chardata[i].x0 = (stbtt_int16) x;
3846 chardata[i].y0 = (stbtt_int16) y;
3847 chardata[i].x1 = (stbtt_int16) (x + gw);
3848 chardata[i].y1 = (stbtt_int16) (y + gh);
3849 chardata[i].xadvance = scale * advance;
3850 chardata[i].xoff = (float) x0;
3851 chardata[i].yoff = (float) y0;
3852 x = x + gw + 1;
3853 if (y+gh+1 > bottom_y)
3854 bottom_y = y+gh+1;
3855 }
3856 return bottom_y;
3857 }
3858
3859 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
3860 {
3861 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
3862 float ipw = 1.0f / pw, iph = 1.0f / ph;
3863 const stbtt_bakedchar *b = chardata + char_index;
3864 int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
3865 int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
3866
3867 q->x0 = round_x + d3d_bias;
3868 q->y0 = round_y + d3d_bias;
3869 q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
3870 q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
3871
3872 q->s0 = b->x0 * ipw;
3873 q->t0 = b->y0 * iph;
3874 q->s1 = b->x1 * ipw;
3875 q->t1 = b->y1 * iph;
3876
3877 *xpos += b->xadvance;
3878 }
3879
3880
3881
3882
3883
3884
3885 #ifndef STB_RECT_PACK_VERSION
3886
3887 typedef int stbrp_coord;
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900 typedef struct
3901 {
3902 int width,height;
3903 int x,y,bottom_y;
3904 } stbrp_context;
3905
3906 typedef struct
3907 {
3908 unsigned char x;
3909 } stbrp_node;
3910
3911 struct stbrp_rect
3912 {
3913 stbrp_coord x,y;
3914 int id,w,h,was_packed;
3915 };
3916
3917 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
3918 {
3919 con->width = pw;
3920 con->height = ph;
3921 con->x = 0;
3922 con->y = 0;
3923 con->bottom_y = 0;
3924 STBTT__NOTUSED(nodes);
3925 STBTT__NOTUSED(num_nodes);
3926 }
3927
3928 static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
3929 {
3930 int i;
3931 for (i=0; i < num_rects; ++i) {
3932 if (con->x + rects[i].w > con->width) {
3933 con->x = 0;
3934 con->y = con->bottom_y;
3935 }
3936 if (con->y + rects[i].h > con->height)
3937 break;
3938 rects[i].x = con->x;
3939 rects[i].y = con->y;
3940 rects[i].was_packed = 1;
3941 con->x += rects[i].w;
3942 if (con->y + rects[i].h > con->bottom_y)
3943 con->bottom_y = con->y + rects[i].h;
3944 }
3945 for ( ; i < num_rects; ++i)
3946 rects[i].was_packed = 0;
3947 }
3948 #endif
3949
3950
3951
3952
3953
3954
3955
3956
3957 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
3958 {
3959 stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
3960 int num_nodes = pw - padding;
3961 stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
3962
3963 if (context == NULL || nodes == NULL) {
3964 if (context != NULL) STBTT_free(context, alloc_context);
3965 if (nodes != NULL) STBTT_free(nodes , alloc_context);
3966 return 0;
3967 }
3968
3969 spc->user_allocator_context = alloc_context;
3970 spc->width = pw;
3971 spc->height = ph;
3972 spc->pixels = pixels;
3973 spc->pack_info = context;
3974 spc->nodes = nodes;
3975 spc->padding = padding;
3976 spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
3977 spc->h_oversample = 1;
3978 spc->v_oversample = 1;
3979 spc->skip_missing = 0;
3980
3981 stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
3982
3983 if (pixels)
3984 STBTT_memset(pixels, 0, pw*ph);
3985
3986 return 1;
3987 }
3988
3989 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
3990 {
3991 STBTT_free(spc->nodes , spc->user_allocator_context);
3992 STBTT_free(spc->pack_info, spc->user_allocator_context);
3993 }
3994
3995 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
3996 {
3997 STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
3998 STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
3999 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
4000 spc->h_oversample = h_oversample;
4001 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
4002 spc->v_oversample = v_oversample;
4003 }
4004
4005 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
4006 {
4007 spc->skip_missing = skip;
4008 }
4009
4010 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
4011
4012 static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
4013 {
4014 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
4015 int safe_w = w - kernel_width;
4016 int j;
4017 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE);
4018 for (j=0; j < h; ++j) {
4019 int i;
4020 unsigned int total;
4021 STBTT_memset(buffer, 0, kernel_width);
4022
4023 total = 0;
4024
4025
4026 switch (kernel_width) {
4027 case 2:
4028 for (i=0; i <= safe_w; ++i) {
4029 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4030 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
4031 pixels[i] = (unsigned char) (total / 2);
4032 }
4033 break;
4034 case 3:
4035 for (i=0; i <= safe_w; ++i) {
4036 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4037 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
4038 pixels[i] = (unsigned char) (total / 3);
4039 }
4040 break;
4041 case 4:
4042 for (i=0; i <= safe_w; ++i) {
4043 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4044 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
4045 pixels[i] = (unsigned char) (total / 4);
4046 }
4047 break;
4048 case 5:
4049 for (i=0; i <= safe_w; ++i) {
4050 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4051 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
4052 pixels[i] = (unsigned char) (total / 5);
4053 }
4054 break;
4055 default:
4056 for (i=0; i <= safe_w; ++i) {
4057 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
4058 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
4059 pixels[i] = (unsigned char) (total / kernel_width);
4060 }
4061 break;
4062 }
4063
4064 for (; i < w; ++i) {
4065 STBTT_assert(pixels[i] == 0);
4066 total -= buffer[i & STBTT__OVER_MASK];
4067 pixels[i] = (unsigned char) (total / kernel_width);
4068 }
4069
4070 pixels += stride_in_bytes;
4071 }
4072 }
4073
4074 static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
4075 {
4076 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
4077 int safe_h = h - kernel_width;
4078 int j;
4079 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE);
4080 for (j=0; j < w; ++j) {
4081 int i;
4082 unsigned int total;
4083 STBTT_memset(buffer, 0, kernel_width);
4084
4085 total = 0;
4086
4087
4088 switch (kernel_width) {
4089 case 2:
4090 for (i=0; i <= safe_h; ++i) {
4091 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4092 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
4093 pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
4094 }
4095 break;
4096 case 3:
4097 for (i=0; i <= safe_h; ++i) {
4098 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4099 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
4100 pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
4101 }
4102 break;
4103 case 4:
4104 for (i=0; i <= safe_h; ++i) {
4105 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4106 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
4107 pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
4108 }
4109 break;
4110 case 5:
4111 for (i=0; i <= safe_h; ++i) {
4112 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4113 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
4114 pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
4115 }
4116 break;
4117 default:
4118 for (i=0; i <= safe_h; ++i) {
4119 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
4120 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
4121 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
4122 }
4123 break;
4124 }
4125
4126 for (; i < h; ++i) {
4127 STBTT_assert(pixels[i*stride_in_bytes] == 0);
4128 total -= buffer[i & STBTT__OVER_MASK];
4129 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
4130 }
4131
4132 pixels += 1;
4133 }
4134 }
4135
4136 static float stbtt__oversample_shift(int oversample)
4137 {
4138 if (!oversample)
4139 return 0.0f;
4140
4141
4142
4143
4144
4145 return (float)-(oversample - 1) / (2.0f * (float)oversample);
4146 }
4147
4148
4149 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
4150 {
4151 int i,j,k;
4152 int missing_glyph_added = 0;
4153
4154 k=0;
4155 for (i=0; i < num_ranges; ++i) {
4156 float fh = ranges[i].font_size;
4157 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
4158 ranges[i].h_oversample = (unsigned char) spc->h_oversample;
4159 ranges[i].v_oversample = (unsigned char) spc->v_oversample;
4160 for (j=0; j < ranges[i].num_chars; ++j) {
4161 int x0,y0,x1,y1;
4162 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4163 int glyph = stbtt_FindGlyphIndex(info, codepoint);
4164 if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
4165 rects[k].w = rects[k].h = 0;
4166 } else {
4167 stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
4168 scale * spc->h_oversample,
4169 scale * spc->v_oversample,
4170 0,0,
4171 &x0,&y0,&x1,&y1);
4172 rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
4173 rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
4174 if (glyph == 0)
4175 missing_glyph_added = 1;
4176 }
4177 ++k;
4178 }
4179 }
4180
4181 return k;
4182 }
4183
4184 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
4185 {
4186 stbtt_MakeGlyphBitmapSubpixel(info,
4187 output,
4188 out_w - (prefilter_x - 1),
4189 out_h - (prefilter_y - 1),
4190 out_stride,
4191 scale_x,
4192 scale_y,
4193 shift_x,
4194 shift_y,
4195 glyph);
4196
4197 if (prefilter_x > 1)
4198 stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
4199
4200 if (prefilter_y > 1)
4201 stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
4202
4203 *sub_x = stbtt__oversample_shift(prefilter_x);
4204 *sub_y = stbtt__oversample_shift(prefilter_y);
4205 }
4206
4207
4208 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
4209 {
4210 int i,j,k, missing_glyph = -1, return_value = 1;
4211
4212
4213 int old_h_over = spc->h_oversample;
4214 int old_v_over = spc->v_oversample;
4215
4216 k = 0;
4217 for (i=0; i < num_ranges; ++i) {
4218 float fh = ranges[i].font_size;
4219 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
4220 float recip_h,recip_v,sub_x,sub_y;
4221 spc->h_oversample = ranges[i].h_oversample;
4222 spc->v_oversample = ranges[i].v_oversample;
4223 recip_h = 1.0f / spc->h_oversample;
4224 recip_v = 1.0f / spc->v_oversample;
4225 sub_x = stbtt__oversample_shift(spc->h_oversample);
4226 sub_y = stbtt__oversample_shift(spc->v_oversample);
4227 for (j=0; j < ranges[i].num_chars; ++j) {
4228 stbrp_rect *r = &rects[k];
4229 if (r->was_packed && r->w != 0 && r->h != 0) {
4230 stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
4231 int advance, lsb, x0,y0,x1,y1;
4232 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
4233 int glyph = stbtt_FindGlyphIndex(info, codepoint);
4234 stbrp_coord pad = (stbrp_coord) spc->padding;
4235
4236
4237 r->x += pad;
4238 r->y += pad;
4239 r->w -= pad;
4240 r->h -= pad;
4241 stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
4242 stbtt_GetGlyphBitmapBox(info, glyph,
4243 scale * spc->h_oversample,
4244 scale * spc->v_oversample,
4245 &x0,&y0,&x1,&y1);
4246 stbtt_MakeGlyphBitmapSubpixel(info,
4247 spc->pixels + r->x + r->y*spc->stride_in_bytes,
4248 r->w - spc->h_oversample+1,
4249 r->h - spc->v_oversample+1,
4250 spc->stride_in_bytes,
4251 scale * spc->h_oversample,
4252 scale * spc->v_oversample,
4253 0,0,
4254 glyph);
4255
4256 if (spc->h_oversample > 1)
4257 stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
4258 r->w, r->h, spc->stride_in_bytes,
4259 spc->h_oversample);
4260
4261 if (spc->v_oversample > 1)
4262 stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
4263 r->w, r->h, spc->stride_in_bytes,
4264 spc->v_oversample);
4265
4266 bc->x0 = (stbtt_int16) r->x;
4267 bc->y0 = (stbtt_int16) r->y;
4268 bc->x1 = (stbtt_int16) (r->x + r->w);
4269 bc->y1 = (stbtt_int16) (r->y + r->h);
4270 bc->xadvance = scale * advance;
4271 bc->xoff = (float) x0 * recip_h + sub_x;
4272 bc->yoff = (float) y0 * recip_v + sub_y;
4273 bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
4274 bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
4275
4276 if (glyph == 0)
4277 missing_glyph = j;
4278 } else if (spc->skip_missing) {
4279 return_value = 0;
4280 } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
4281 ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
4282 } else {
4283 return_value = 0;
4284 }
4285
4286 ++k;
4287 }
4288 }
4289
4290
4291 spc->h_oversample = old_h_over;
4292 spc->v_oversample = old_v_over;
4293
4294 return return_value;
4295 }
4296
4297 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
4298 {
4299 stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
4300 }
4301
4302 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
4303 {
4304 stbtt_fontinfo info;
4305 int i,j,n, return_value = 1;
4306
4307 stbrp_rect *rects;
4308
4309
4310 for (i=0; i < num_ranges; ++i)
4311 for (j=0; j < ranges[i].num_chars; ++j)
4312 ranges[i].chardata_for_range[j].x0 =
4313 ranges[i].chardata_for_range[j].y0 =
4314 ranges[i].chardata_for_range[j].x1 =
4315 ranges[i].chardata_for_range[j].y1 = 0;
4316
4317 n = 0;
4318 for (i=0; i < num_ranges; ++i)
4319 n += ranges[i].num_chars;
4320
4321 rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
4322 if (rects == NULL)
4323 return 0;
4324
4325 info.userdata = spc->user_allocator_context;
4326 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
4327
4328 n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
4329
4330 stbtt_PackFontRangesPackRects(spc, rects, n);
4331
4332 return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
4333
4334 STBTT_free(rects, spc->user_allocator_context);
4335 return return_value;
4336 }
4337
4338 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
4339 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
4340 {
4341 stbtt_pack_range range;
4342 range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
4343 range.array_of_unicode_codepoints = NULL;
4344 range.num_chars = num_chars_in_range;
4345 range.chardata_for_range = chardata_for_range;
4346 range.font_size = font_size;
4347 return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
4348 }
4349
4350 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
4351 {
4352 int i_ascent, i_descent, i_lineGap;
4353 float scale;
4354 stbtt_fontinfo info;
4355 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
4356 scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
4357 stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
4358 *ascent = (float) i_ascent * scale;
4359 *descent = (float) i_descent * scale;
4360 *lineGap = (float) i_lineGap * scale;
4361 }
4362
4363 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
4364 {
4365 float ipw = 1.0f / pw, iph = 1.0f / ph;
4366 const stbtt_packedchar *b = chardata + char_index;
4367
4368 if (align_to_integer) {
4369 float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
4370 float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
4371 q->x0 = x;
4372 q->y0 = y;
4373 q->x1 = x + b->xoff2 - b->xoff;
4374 q->y1 = y + b->yoff2 - b->yoff;
4375 } else {
4376 q->x0 = *xpos + b->xoff;
4377 q->y0 = *ypos + b->yoff;
4378 q->x1 = *xpos + b->xoff2;
4379 q->y1 = *ypos + b->yoff2;
4380 }
4381
4382 q->s0 = b->x0 * ipw;
4383 q->t0 = b->y0 * iph;
4384 q->s1 = b->x1 * ipw;
4385 q->t1 = b->y1 * iph;
4386
4387 *xpos += b->xadvance;
4388 }
4389
4390
4391
4392
4393
4394
4395 #define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
4396 #define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
4397
4398 static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
4399 {
4400 float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
4401 float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
4402 float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
4403 float roperp = orig[1]*ray[0] - orig[0]*ray[1];
4404
4405 float a = q0perp - 2*q1perp + q2perp;
4406 float b = q1perp - q0perp;
4407 float c = q0perp - roperp;
4408
4409 float s0 = 0., s1 = 0.;
4410 int num_s = 0;
4411
4412 if (a != 0.0) {
4413 float discr = b*b - a*c;
4414 if (discr > 0.0) {
4415 float rcpna = -1 / a;
4416 float d = (float) STBTT_sqrt(discr);
4417 s0 = (b+d) * rcpna;
4418 s1 = (b-d) * rcpna;
4419 if (s0 >= 0.0 && s0 <= 1.0)
4420 num_s = 1;
4421 if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
4422 if (num_s == 0) s0 = s1;
4423 ++num_s;
4424 }
4425 }
4426 } else {
4427
4428
4429 s0 = c / (-2 * b);
4430 if (s0 >= 0.0 && s0 <= 1.0)
4431 num_s = 1;
4432 }
4433
4434 if (num_s == 0)
4435 return 0;
4436 else {
4437 float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
4438 float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
4439
4440 float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
4441 float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
4442 float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
4443 float rod = orig[0]*rayn_x + orig[1]*rayn_y;
4444
4445 float q10d = q1d - q0d;
4446 float q20d = q2d - q0d;
4447 float q0rd = q0d - rod;
4448
4449 hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
4450 hits[0][1] = a*s0+b;
4451
4452 if (num_s > 1) {
4453 hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
4454 hits[1][1] = a*s1+b;
4455 return 2;
4456 } else {
4457 return 1;
4458 }
4459 }
4460 }
4461
4462 static int equal(float *a, float *b)
4463 {
4464 return (a[0] == b[0] && a[1] == b[1]);
4465 }
4466
4467 static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
4468 {
4469 int i;
4470 float orig[2], ray[2] = { 1, 0 };
4471 float y_frac;
4472 int winding = 0;
4473
4474
4475 y_frac = (float) STBTT_fmod(y, 1.0f);
4476 if (y_frac < 0.01f)
4477 y += 0.01f;
4478 else if (y_frac > 0.99f)
4479 y -= 0.01f;
4480
4481 orig[0] = x;
4482 orig[1] = y;
4483
4484
4485 for (i=0; i < nverts; ++i) {
4486 if (verts[i].type == STBTT_vline) {
4487 int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
4488 int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
4489 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4490 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4491 if (x_inter < x)
4492 winding += (y0 < y1) ? 1 : -1;
4493 }
4494 }
4495 if (verts[i].type == STBTT_vcurve) {
4496 int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
4497 int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
4498 int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
4499 int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
4500 int by = STBTT_max(y0,STBTT_max(y1,y2));
4501 if (y > ay && y < by && x > ax) {
4502 float q0[2],q1[2],q2[2];
4503 float hits[2][2];
4504 q0[0] = (float)x0;
4505 q0[1] = (float)y0;
4506 q1[0] = (float)x1;
4507 q1[1] = (float)y1;
4508 q2[0] = (float)x2;
4509 q2[1] = (float)y2;
4510 if (equal(q0,q1) || equal(q1,q2)) {
4511 x0 = (int)verts[i-1].x;
4512 y0 = (int)verts[i-1].y;
4513 x1 = (int)verts[i ].x;
4514 y1 = (int)verts[i ].y;
4515 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4516 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4517 if (x_inter < x)
4518 winding += (y0 < y1) ? 1 : -1;
4519 }
4520 } else {
4521 int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
4522 if (num_hits >= 1)
4523 if (hits[0][0] < 0)
4524 winding += (hits[0][1] < 0 ? -1 : 1);
4525 if (num_hits >= 2)
4526 if (hits[1][0] < 0)
4527 winding += (hits[1][1] < 0 ? -1 : 1);
4528 }
4529 }
4530 }
4531 }
4532 return winding;
4533 }
4534
4535 static float stbtt__cuberoot( float x )
4536 {
4537 if (x<0)
4538 return -(float) STBTT_pow(-x,1.0f/3.0f);
4539 else
4540 return (float) STBTT_pow( x,1.0f/3.0f);
4541 }
4542
4543
4544 static int stbtt__solve_cubic(float a, float b, float c, float* r)
4545 {
4546 float s = -a / 3;
4547 float p = b - a*a / 3;
4548 float q = a * (2*a*a - 9*b) / 27 + c;
4549 float p3 = p*p*p;
4550 float d = q*q + 4*p3 / 27;
4551 if (d >= 0) {
4552 float z = (float) STBTT_sqrt(d);
4553 float u = (-q + z) / 2;
4554 float v = (-q - z) / 2;
4555 u = stbtt__cuberoot(u);
4556 v = stbtt__cuberoot(v);
4557 r[0] = s + u + v;
4558 return 1;
4559 } else {
4560 float u = (float) STBTT_sqrt(-p/3);
4561 float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3;
4562 float m = (float) STBTT_cos(v);
4563 float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
4564 r[0] = s + u * 2 * m;
4565 r[1] = s - u * (m + n);
4566 r[2] = s - u * (m - n);
4567
4568
4569
4570
4571 return 3;
4572 }
4573 }
4574
4575 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
4576 {
4577 float scale_x = scale, scale_y = scale;
4578 int ix0,iy0,ix1,iy1;
4579 int w,h;
4580 unsigned char *data;
4581
4582 if (scale == 0) return NULL;
4583
4584 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
4585
4586
4587 if (ix0 == ix1 || iy0 == iy1)
4588 return NULL;
4589
4590 ix0 -= padding;
4591 iy0 -= padding;
4592 ix1 += padding;
4593 iy1 += padding;
4594
4595 w = (ix1 - ix0);
4596 h = (iy1 - iy0);
4597
4598 if (width ) *width = w;
4599 if (height) *height = h;
4600 if (xoff ) *xoff = ix0;
4601 if (yoff ) *yoff = iy0;
4602
4603
4604 scale_y = -scale_y;
4605
4606 {
4607
4608 const float eps = 1./1024, eps2 = eps*eps;
4609 int x,y,i,j;
4610 float *precompute;
4611 stbtt_vertex *verts;
4612 int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
4613 data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
4614 precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
4615
4616 for (i=0,j=num_verts-1; i < num_verts; j=i++) {
4617 if (verts[i].type == STBTT_vline) {
4618 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
4619 float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
4620 float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
4621 precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist;
4622 } else if (verts[i].type == STBTT_vcurve) {
4623 float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
4624 float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
4625 float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
4626 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4627 float len2 = bx*bx + by*by;
4628 if (len2 >= eps2)
4629 precompute[i] = 1.0f / len2;
4630 else
4631 precompute[i] = 0.0f;
4632 } else
4633 precompute[i] = 0.0f;
4634 }
4635
4636 for (y=iy0; y < iy1; ++y) {
4637 for (x=ix0; x < ix1; ++x) {
4638 float val;
4639 float min_dist = 999999.0f;
4640 float sx = (float) x + 0.5f;
4641 float sy = (float) y + 0.5f;
4642 float x_gspace = (sx / scale_x);
4643 float y_gspace = (sy / scale_y);
4644
4645 int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts);
4646
4647 for (i=0; i < num_verts; ++i) {
4648 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
4649
4650 if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
4651 float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
4652
4653 float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4654 if (dist2 < min_dist*min_dist)
4655 min_dist = (float) STBTT_sqrt(dist2);
4656
4657
4658
4659
4660 dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
4661 STBTT_assert(i != 0);
4662 if (dist < min_dist) {
4663
4664
4665
4666 float dx = x1-x0, dy = y1-y0;
4667 float px = x0-sx, py = y0-sy;
4668
4669
4670 float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
4671 if (t >= 0.0f && t <= 1.0f)
4672 min_dist = dist;
4673 }
4674 } else if (verts[i].type == STBTT_vcurve) {
4675 float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
4676 float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
4677 float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
4678 float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
4679 float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
4680 float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
4681
4682 if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
4683 int num=0;
4684 float ax = x1-x0, ay = y1-y0;
4685 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4686 float mx = x0 - sx, my = y0 - sy;
4687 float res[3] = {0.f,0.f,0.f};
4688 float px,py,t,it,dist2;
4689 float a_inv = precompute[i];
4690 if (a_inv == 0.0) {
4691 float a = 3*(ax*bx + ay*by);
4692 float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
4693 float c = mx*ax+my*ay;
4694 if (STBTT_fabs(a) < eps2) {
4695 if (STBTT_fabs(b) >= eps2) {
4696 res[num++] = -c/b;
4697 }
4698 } else {
4699 float discriminant = b*b - 4*a*c;
4700 if (discriminant < 0)
4701 num = 0;
4702 else {
4703 float root = (float) STBTT_sqrt(discriminant);
4704 res[0] = (-b - root)/(2*a);
4705 res[1] = (-b + root)/(2*a);
4706 num = 2;
4707 }
4708 }
4709 } else {
4710 float b = 3*(ax*bx + ay*by) * a_inv;
4711 float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
4712 float d = (mx*ax+my*ay) * a_inv;
4713 num = stbtt__solve_cubic(b, c, d, res);
4714 }
4715 dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4716 if (dist2 < min_dist*min_dist)
4717 min_dist = (float) STBTT_sqrt(dist2);
4718
4719 if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
4720 t = res[0], it = 1.0f - t;
4721 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4722 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4723 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4724 if (dist2 < min_dist * min_dist)
4725 min_dist = (float) STBTT_sqrt(dist2);
4726 }
4727 if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
4728 t = res[1], it = 1.0f - t;
4729 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4730 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4731 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4732 if (dist2 < min_dist * min_dist)
4733 min_dist = (float) STBTT_sqrt(dist2);
4734 }
4735 if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
4736 t = res[2], it = 1.0f - t;
4737 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4738 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4739 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4740 if (dist2 < min_dist * min_dist)
4741 min_dist = (float) STBTT_sqrt(dist2);
4742 }
4743 }
4744 }
4745 }
4746 if (winding == 0)
4747 min_dist = -min_dist;
4748 val = onedge_value + pixel_dist_scale * min_dist;
4749 if (val < 0)
4750 val = 0;
4751 else if (val > 255)
4752 val = 255;
4753 data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
4754 }
4755 }
4756 STBTT_free(precompute, info->userdata);
4757 STBTT_free(verts, info->userdata);
4758 }
4759 return data;
4760 }
4761
4762 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
4763 {
4764 return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
4765 }
4766
4767 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
4768 {
4769 STBTT_free(bitmap, userdata);
4770 }
4771
4772
4773
4774
4775
4776
4777
4778 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
4779 {
4780 stbtt_int32 i=0;
4781
4782
4783 while (len2) {
4784 stbtt_uint16 ch = s2[0]*256 + s2[1];
4785 if (ch < 0x80) {
4786 if (i >= len1) return -1;
4787 if (s1[i++] != ch) return -1;
4788 } else if (ch < 0x800) {
4789 if (i+1 >= len1) return -1;
4790 if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
4791 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
4792 } else if (ch >= 0xd800 && ch < 0xdc00) {
4793 stbtt_uint32 c;
4794 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
4795 if (i+3 >= len1) return -1;
4796 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
4797 if (s1[i++] != 0xf0 + (c >> 18)) return -1;
4798 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
4799 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
4800 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
4801 s2 += 2;
4802 len2 -= 2;
4803 } else if (ch >= 0xdc00 && ch < 0xe000) {
4804 return -1;
4805 } else {
4806 if (i+2 >= len1) return -1;
4807 if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
4808 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
4809 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
4810 }
4811 s2 += 2;
4812 len2 -= 2;
4813 }
4814 return i;
4815 }
4816
4817 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
4818 {
4819 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
4820 }
4821
4822
4823
4824 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
4825 {
4826 stbtt_int32 i,count,stringOffset;
4827 stbtt_uint8 *fc = font->data;
4828 stbtt_uint32 offset = font->fontstart;
4829 stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
4830 if (!nm) return NULL;
4831
4832 count = ttUSHORT(fc+nm+2);
4833 stringOffset = nm + ttUSHORT(fc+nm+4);
4834 for (i=0; i < count; ++i) {
4835 stbtt_uint32 loc = nm + 6 + 12 * i;
4836 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
4837 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
4838 *length = ttUSHORT(fc+loc+8);
4839 return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
4840 }
4841 }
4842 return NULL;
4843 }
4844
4845 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
4846 {
4847 stbtt_int32 i;
4848 stbtt_int32 count = ttUSHORT(fc+nm+2);
4849 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
4850
4851 for (i=0; i < count; ++i) {
4852 stbtt_uint32 loc = nm + 6 + 12 * i;
4853 stbtt_int32 id = ttUSHORT(fc+loc+6);
4854 if (id == target_id) {
4855
4856 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
4857
4858
4859 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
4860 stbtt_int32 slen = ttUSHORT(fc+loc+8);
4861 stbtt_int32 off = ttUSHORT(fc+loc+10);
4862
4863
4864 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
4865 if (matchlen >= 0) {
4866
4867 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) {
4868 slen = ttUSHORT(fc+loc+12+8);
4869 off = ttUSHORT(fc+loc+12+10);
4870 if (slen == 0) {
4871 if (matchlen == nlen)
4872 return 1;
4873 } else if (matchlen < nlen && name[matchlen] == ' ') {
4874 ++matchlen;
4875 if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
4876 return 1;
4877 }
4878 } else {
4879
4880 if (matchlen == nlen)
4881 return 1;
4882 }
4883 }
4884 }
4885
4886
4887 }
4888 }
4889 return 0;
4890 }
4891
4892 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
4893 {
4894 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
4895 stbtt_uint32 nm,hd;
4896 if (!stbtt__isfont(fc+offset)) return 0;
4897
4898
4899 if (flags) {
4900 hd = stbtt__find_table(fc, offset, "head");
4901 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
4902 }
4903
4904 nm = stbtt__find_table(fc, offset, "name");
4905 if (!nm) return 0;
4906
4907 if (flags) {
4908
4909 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
4910 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
4911 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4912 } else {
4913 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
4914 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
4915 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
4916 }
4917
4918 return 0;
4919 }
4920
4921 static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
4922 {
4923 stbtt_int32 i;
4924 for (i=0;;++i) {
4925 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
4926 if (off < 0) return off;
4927 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
4928 return off;
4929 }
4930 }
4931
4932 #if defined(__GNUC__) || defined(__clang__)
4933 #pragma GCC diagnostic push
4934 #pragma GCC diagnostic ignored "-Wcast-qual"
4935 #endif
4936
4937 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
4938 float pixel_height, unsigned char *pixels, int pw, int ph,
4939 int first_char, int num_chars, stbtt_bakedchar *chardata)
4940 {
4941 return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
4942 }
4943
4944 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
4945 {
4946 return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
4947 }
4948
4949 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
4950 {
4951 return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
4952 }
4953
4954 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
4955 {
4956 return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
4957 }
4958
4959 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
4960 {
4961 return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
4962 }
4963
4964 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
4965 {
4966 return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
4967 }
4968
4969 #if defined(__GNUC__) || defined(__clang__)
4970 #pragma GCC diagnostic pop
4971 #endif
4972
4973 #endif
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079