00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00085
00086
00087
00088 #if 0
00089 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
00090 #include "stb_truetype.h"
00091
00092 char ttf_buffer[1<<20];
00093 unsigned char temp_bitmap[512*512];
00094
00095 stbtt_chardata cdata[96];
00096 GLstbtt_uint ftex;
00097
00098 void my_stbtt_initfont(void)
00099 {
00100 fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
00101 stbtt_BakeFontBitmap(data,0, 32.0, temp_bitmap,512,512, 32,96, cdata);
00102
00103 glGenTextures(1, &ftex);
00104 glBindTexture(GL_TEXTURE_2D, ftex);
00105 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
00106
00107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00108 }
00109
00110 void my_stbtt_print(float x, float y, char *text)
00111 {
00112
00113 glBindTexture(GL_TEXTURE_2D, ftex);
00114 glBegin(GL_QUADS);
00115 while (*text) {
00116 if (*text >= 32 && *text < 128) {
00117 stbtt_aligned_quad q;
00118 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);
00119 glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
00120 glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
00121 glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
00122 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
00123 }
00124 ++text;
00125 }
00126 glEnd();
00127 }
00128 #endif
00129
00130
00132
00133
00134
00135 #if 0
00136 #include <stdio.h>
00137 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
00138 #include "stb_truetype.h"
00139
00140 char ttf_buffer[1<<25];
00141
00142 int main(int argc, char **argv)
00143 {
00144 stbtt_fontinfo font;
00145 unsigned char *bitmap;
00146 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
00147
00148 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
00149
00150 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
00151 bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
00152
00153 for (j=0; j < h; ++j) {
00154 for (i=0; i < w; ++i)
00155 putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
00156 putchar('\n');
00157 }
00158 return 0;
00159 }
00160 #endif
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00176
00177
00178
00179 #if 0
00180 int main(int arg, char **argv)
00181 {
00182 unsigned char screen[20][79];
00183 int i,j, pos=0;
00184 float scale;
00185 char *text = "Heljo World!";
00186
00187 fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
00188 stbtt_InitFont(&font, buffer, 0);
00189
00190 scale = stbtt_ScaleForPixelHeight(&font, 16);
00191 memset(screen, 0, sizeof(screen));
00192
00193 while (*text) {
00194 int advance,lsb,x0,y0,x1,y1, newpos, baseline=13;
00195 stbtt_GetCodepointHMetrics(&font, *text, &advance, &lsb);
00196 stbtt_GetCodepointBitmapBox(&font, *text, scale,scale, &x0,&y0,&x1,&y1);
00197 newpos = pos + (int) (lsb * scale) + x0;
00198 stbtt_MakeCodepointBitmap(&font, &screen[baseline + y0][newpos], x1-x0,y1-y0, 79, scale,scale, *text);
00199
00200
00201 pos += (int) (advance * scale);
00202 ++text;
00203 }
00204
00205 for (j=0; j < 20; ++j) {
00206 for (i=0; i < 79; ++i)
00207 putchar(" .:ioVM@"[screen[j][i]>>5]);
00208 putchar('\n');
00209 }
00210
00211 return 0;
00212 }
00213 #endif
00214
00215
00221
00222 #ifdef STB_TRUETYPE_IMPLEMENTATION
00223
00224 #ifndef stbtt_uint8
00225 typedef unsigned char stbtt_uint8;
00226 typedef signed char stbtt_int8;
00227 typedef unsigned short stbtt_uint16;
00228 typedef signed short stbtt_int16;
00229 typedef unsigned int stbtt_uint32;
00230 typedef signed int stbtt_int32;
00231 #endif
00232
00233 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
00234 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
00235
00236
00237 #ifndef STBTT_sort
00238 #include <stdlib.h>
00239 #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
00240 #endif
00241
00242
00243 #ifndef STBTT_ifloor
00244 #include <math.h>
00245 #define STBTT_ifloor(x) ((int) floor(x))
00246 #define STBTT_iceil(x) ((int) ceil(x))
00247 #endif
00248
00249
00250 #ifndef STBTT_malloc
00251 #include <stdlib.h>
00252 #define STBTT_malloc(x,u) malloc(x)
00253 #define STBTT_free(x,u) free(x)
00254 #endif
00255
00256 #ifndef STBTT_assert
00257 #include <assert.h>
00258 #define STBTT_assert(x) assert(x)
00259 #endif
00260
00261 #ifndef STBTT_strlen
00262 #include <string.h>
00263 #define STBTT_strlen(x) strlen(x)
00264 #endif
00265
00266 #ifndef STBTT_memcpy
00267 #include <memory.h>
00268 #define STBTT_memcpy memcpy
00269 #define STBTT_memset memset
00270 #endif
00271 #endif
00272
00279
00280 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
00281 #define __STB_INCLUDE_STB_TRUETYPE_H__
00282
00283 #ifdef __cplusplus
00284 extern "C" {
00285 #endif
00286
00288
00289
00290
00291
00292
00293
00294 typedef struct
00295 {
00296 unsigned short x0,y0,x1,y1;
00297 float xoff,yoff,xadvance;
00298 } stbtt_bakedchar;
00299
00300 extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
00301 float pixel_height,
00302 unsigned char *pixels, int pw, int ph,
00303 int first_char, int num_chars,
00304 stbtt_bakedchar *chardata);
00305
00306
00307
00308
00309
00310 typedef struct
00311 {
00312 float x0,y0,s0,t0;
00313 float x1,y1,s1,t1;
00314 } stbtt_aligned_quad;
00315
00316 extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph,
00317 int char_index,
00318 float *xpos, float *ypos,
00319 stbtt_aligned_quad *q,
00320 int opengl_fillrule);
00321
00322
00323
00324
00325
00327
00328
00329
00330
00331
00332 extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 typedef struct
00344 {
00345 void *userdata;
00346 unsigned char *data;
00347 int fontstart;
00348
00349 int numGlyphs;
00350
00351 int loca,head,glyf,hhea,hmtx;
00352 int index_map;
00353 int indexToLocFormat;
00354 } stbtt_fontinfo;
00355
00356 extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
00357
00358
00359
00360
00361
00362
00363
00365
00366
00367
00368 int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
00369
00370
00371
00372
00373
00374
00376
00377
00378
00379
00380 extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
00381
00382
00383
00384
00385
00386
00387
00388 extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
00389
00390
00391
00392
00393
00394
00395 extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
00396
00397
00398
00399
00400 extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
00401
00402
00403
00404 extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
00405
00406
00407 extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
00408 extern int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
00409 extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
00410
00411
00412
00414
00415
00416
00417
00418
00419 #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
00420 enum {
00421 STBTT_vmove=1,
00422 STBTT_vline,
00423 STBTT_vcurve
00424 };
00425 #endif
00426
00427 #ifndef stbtt_vertex // you can predefine this to use different values
00428
00429 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
00430 typedef struct
00431 {
00432 stbtt_vertex_type x,y,cx,cy;
00433 unsigned char type,padding;
00434 } stbtt_vertex;
00435 #endif
00436
00437 extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
00438 extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
00439
00440
00441
00442 extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
00443
00444
00446
00447
00448
00449
00450 extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
00451
00452
00453 extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
00454
00455
00456
00457
00458
00459
00460
00461
00462 extern 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);
00463
00464
00465
00466
00467
00468 extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
00469
00470
00471
00472
00473
00474
00475 extern unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
00476 extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
00477 extern 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);
00478
00479
00480
00481
00482 typedef struct
00483 {
00484 int w,h,stride;
00485 unsigned char *pixels;
00486 } stbtt__bitmap;
00487
00488 extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata);
00489
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
00513
00514
00515
00516
00517 #define STBTT_MACSTYLE_DONTCARE 0
00518 #define STBTT_MACSTYLE_BOLD 1
00519 #define STBTT_MACSTYLE_ITALIC 2
00520 #define STBTT_MACSTYLE_UNDERSCORE 4
00521 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
00522
00523 extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
00524
00525
00526
00527 extern char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
00528
00529
00530
00531
00532
00533
00534
00535 enum {
00536 STBTT_PLATFORM_ID_UNICODE =0,
00537 STBTT_PLATFORM_ID_MAC =1,
00538 STBTT_PLATFORM_ID_ISO =2,
00539 STBTT_PLATFORM_ID_MICROSOFT =3
00540 };
00541
00542 enum {
00543 STBTT_UNICODE_EID_UNICODE_1_0 =0,
00544 STBTT_UNICODE_EID_UNICODE_1_1 =1,
00545 STBTT_UNICODE_EID_ISO_10646 =2,
00546 STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
00547 STBTT_UNICODE_EID_UNICODE_2_0_FULL=4,
00548 };
00549
00550 enum {
00551 STBTT_MS_EID_SYMBOL =0,
00552 STBTT_MS_EID_UNICODE_BMP =1,
00553 STBTT_MS_EID_SHIFTJIS =2,
00554 STBTT_MS_EID_UNICODE_FULL =10,
00555 };
00556
00557 enum {
00558 STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
00559 STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
00560 STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
00561 STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7,
00562 };
00563
00564 enum {
00565
00566 STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
00567 STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
00568 STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
00569 STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
00570 STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
00571 STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D,
00572 };
00573
00574 enum {
00575 STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
00576 STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
00577 STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
00578 STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
00579 STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
00580 STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
00581 STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19,
00582 };
00583
00584 #ifdef __cplusplus
00585 }
00586 #endif
00587
00588 #endif // __STB_INCLUDE_STB_TRUETYPE_H__
00589
00596
00597 #ifdef STB_TRUETYPE_IMPLEMENTATION
00598
00600
00601
00602
00603
00604
00605
00606
00607 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
00608 #define ttCHAR(p) (* (stbtt_int8 *) (p))
00609 #define ttFixed(p) ttLONG(p)
00610
00611 #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
00612
00613 #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
00614 #define ttSHORT(p) (* (stbtt_int16 *) (p))
00615 #define ttULONG(p) (* (stbtt_uint32 *) (p))
00616 #define ttLONG(p) (* (stbtt_int32 *) (p))
00617
00618 #else
00619
00620 stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
00621 stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; }
00622 stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
00623 stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
00624
00625 #endif
00626
00627 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
00628 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
00629
00630 static int stbtt__isfont(const stbtt_uint8 *font)
00631 {
00632
00633 if (stbtt_tag(font, "1")) return 1;
00634 if (stbtt_tag(font, "typ1")) return 1;
00635 if (stbtt_tag(font, "OTTO")) return 1;
00636 if (stbtt_tag4(font, 0,1,0,0)) return 1;
00637 return 0;
00638 }
00639
00640
00641 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, char *tag)
00642 {
00643 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
00644 stbtt_uint32 tabledir = fontstart + 12;
00645 stbtt_int32 i;
00646 for (i=0; i < num_tables; ++i) {
00647 stbtt_uint32 loc = tabledir + 16*i;
00648 if (stbtt_tag(data+loc+0, tag))
00649 return ttULONG(data+loc+8);
00650 }
00651 return 0;
00652 }
00653
00654 int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index)
00655 {
00656
00657 if (stbtt__isfont(font_collection))
00658 return index == 0 ? 0 : -1;
00659
00660
00661 if (stbtt_tag(font_collection, "ttcf")) {
00662
00663 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
00664 stbtt_int32 n = ttLONG(font_collection+8);
00665 if (index >= n)
00666 return -1;
00667 return ttULONG(font_collection+12+index*14);
00668 }
00669 }
00670 return -1;
00671 }
00672
00673 int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart)
00674 {
00675 stbtt_uint8 *data = (stbtt_uint8 *) data2;
00676 stbtt_uint32 cmap, t;
00677 stbtt_int32 i,numTables;
00678
00679 info->data = data;
00680 info->fontstart = fontstart;
00681
00682 cmap = stbtt__find_table(data, fontstart, "cmap");
00683 info->loca = stbtt__find_table(data, fontstart, "loca");
00684 info->head = stbtt__find_table(data, fontstart, "head");
00685 info->glyf = stbtt__find_table(data, fontstart, "glyf");
00686 info->hhea = stbtt__find_table(data, fontstart, "hhea");
00687 info->hmtx = stbtt__find_table(data, fontstart, "hmtx");
00688 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
00689 return 0;
00690
00691 t = stbtt__find_table(data, fontstart, "maxp");
00692 if (t)
00693 info->numGlyphs = ttUSHORT(data+t+4);
00694 else
00695 info->numGlyphs = 0xffff;
00696
00697
00698
00699
00700 numTables = ttUSHORT(data + cmap + 2);
00701 info->index_map = 0;
00702 for (i=0; i < numTables; ++i) {
00703 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
00704
00705 switch(ttUSHORT(data+encoding_record)) {
00706 case STBTT_PLATFORM_ID_MICROSOFT:
00707 switch (ttUSHORT(data+encoding_record+2)) {
00708 case STBTT_MS_EID_UNICODE_BMP:
00709 case STBTT_MS_EID_UNICODE_FULL:
00710
00711 info->index_map = cmap + ttULONG(data+encoding_record+4);
00712 break;
00713 }
00714 break;
00715 }
00716 }
00717 if (info->index_map == 0)
00718 return 0;
00719
00720 info->indexToLocFormat = ttUSHORT(data+info->head + 50);
00721 return 1;
00722 }
00723
00724 int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
00725 {
00726 stbtt_uint8 *data = info->data;
00727 stbtt_uint32 index_map = info->index_map;
00728
00729 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
00730 if (format == 0) {
00731 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
00732 if (unicode_codepoint < bytes-6)
00733 return ttBYTE(data + index_map + 6 + unicode_codepoint);
00734 return 0;
00735 } else if (format == 6) {
00736 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
00737 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
00738 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
00739 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
00740 return 0;
00741 } else if (format == 2) {
00742 STBTT_assert(0);
00743 return 0;
00744 } else if (format == 4) {
00745 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
00746 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
00747 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
00748 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
00749 stbtt_uint16 item, offset, start, end;
00750
00751
00752 stbtt_uint32 endCount = index_map + 14;
00753 stbtt_uint32 search = endCount;
00754
00755 if (unicode_codepoint > 0xffff)
00756 return 0;
00757
00758
00759
00760 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
00761 search += rangeShift*2;
00762
00763
00764 search -= 2;
00765 while (entrySelector) {
00766 stbtt_uint16 start, end;
00767 searchRange >>= 1;
00768 start = ttUSHORT(data + search + 2 + segcount*2 + 2);
00769 end = ttUSHORT(data + search + 2);
00770 start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
00771 end = ttUSHORT(data + search + searchRange*2);
00772 if (unicode_codepoint > end)
00773 search += searchRange*2;
00774 --entrySelector;
00775 }
00776 search += 2;
00777
00778 item = (stbtt_uint16) ((search - endCount) >> 1);
00779
00780 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
00781 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
00782 end = ttUSHORT(data + index_map + 14 + 2 + 2*item);
00783 if (unicode_codepoint < start)
00784 return 0;
00785
00786 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
00787 if (offset == 0)
00788 return unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item);
00789
00790 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
00791 } else if (format == 12) {
00792 stbtt_uint16 ngroups = ttUSHORT(data+index_map+6);
00793 stbtt_int32 low,high;
00794 stbtt_uint16 g = 0;
00795 low = 0; high = (stbtt_int32)ngroups;
00796
00797 while (low <= high) {
00798 stbtt_int32 mid = low + ((high-low) >> 1);
00799 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
00800 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
00801 if ((stbtt_uint32) unicode_codepoint < start_char)
00802 high = mid-1;
00803 else if ((stbtt_uint32) unicode_codepoint > end_char)
00804 low = mid+1;
00805 else {
00806 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
00807 return start_glyph + unicode_codepoint-start_char;
00808 }
00809 }
00810 return 0;
00811 }
00812
00813 STBTT_assert(0);
00814 return 0;
00815 }
00816
00817 int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
00818 {
00819 return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
00820 }
00821
00822 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int16 x, stbtt_int16 y, stbtt_int16 cx, stbtt_int16 cy)
00823 {
00824 v->type = type;
00825 v->x = x;
00826 v->y = y;
00827 v->cx = cx;
00828 v->cy = cy;
00829 }
00830
00831 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
00832 {
00833 int g1,g2;
00834
00835 if (glyph_index >= info->numGlyphs) return -1;
00836 if (info->indexToLocFormat >= 2) return -1;
00837
00838 if (info->indexToLocFormat == 0) {
00839 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
00840 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
00841 } else {
00842 g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
00843 g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
00844 }
00845
00846 return g1==g2 ? -1 : g1;
00847 }
00848
00849 int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
00850 {
00851 int g = stbtt__GetGlyfOffset(info, glyph_index);
00852 if (g < 0) return 0;
00853
00854 if (x0) *x0 = ttSHORT(info->data + g + 2);
00855 if (y0) *y0 = ttSHORT(info->data + g + 4);
00856 if (x1) *x1 = ttSHORT(info->data + g + 6);
00857 if (y1) *y1 = ttSHORT(info->data + g + 8);
00858 return 1;
00859 }
00860
00861 int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
00862 {
00863 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
00864 }
00865
00866 int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
00867 {
00868 stbtt_int16 numberOfContours;
00869 stbtt_uint8 *endPtsOfContours;
00870 stbtt_uint8 *data = info->data;
00871 stbtt_vertex *vertices=0;
00872 int num_vertices=0;
00873 int g = stbtt__GetGlyfOffset(info, glyph_index);
00874
00875 *pvertices = NULL;
00876
00877 if (g < 0) return 0;
00878
00879 numberOfContours = ttSHORT(data + g);
00880
00881 if (numberOfContours > 0) {
00882 stbtt_uint8 flags=0,flagcount;
00883 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off;
00884 stbtt_int16 x,y,cx,cy,sx,sy;
00885 stbtt_uint8 *points;
00886 endPtsOfContours = (data + g + 10);
00887 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
00888 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
00889
00890 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
00891
00892 m = n + numberOfContours;
00893 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
00894 if (vertices == 0)
00895 return 0;
00896
00897 next_move = 0;
00898 flagcount=0;
00899
00900
00901
00902
00903
00904 off = m - n;
00905
00906
00907
00908 for (i=0; i < n; ++i) {
00909 if (flagcount == 0) {
00910 flags = *points++;
00911 if (flags & 8)
00912 flagcount = *points++;
00913 } else
00914 --flagcount;
00915 vertices[off+i].type = flags;
00916 }
00917
00918
00919 x=0;
00920 for (i=0; i < n; ++i) {
00921 flags = vertices[off+i].type;
00922 if (flags & 2) {
00923 stbtt_int16 dx = *points++;
00924 x += (flags & 16) ? dx : -dx;
00925 } else {
00926 if (!(flags & 16)) {
00927 x = x + (stbtt_int16) (points[0]*256 + points[1]);
00928 points += 2;
00929 }
00930 }
00931 vertices[off+i].x = x;
00932 }
00933
00934
00935 y=0;
00936 for (i=0; i < n; ++i) {
00937 flags = vertices[off+i].type;
00938 if (flags & 4) {
00939 stbtt_int16 dy = *points++;
00940 y += (flags & 32) ? dy : -dy;
00941 } else {
00942 if (!(flags & 32)) {
00943 y = y + (stbtt_int16) (points[0]*256 + points[1]);
00944 points += 2;
00945 }
00946 }
00947 vertices[off+i].y = y;
00948 }
00949
00950
00951 num_vertices=0;
00952 sx = sy = cx = cy = 0;
00953 for (i=0; i < n; ++i) {
00954 flags = vertices[off+i].type;
00955 x = (stbtt_int16) vertices[off+i].x;
00956 y = (stbtt_int16) vertices[off+i].y;
00957 if (next_move == i) {
00958
00959 if (i != 0) {
00960 if (was_off)
00961 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
00962 else
00963 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
00964 }
00965
00966
00967 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,x,y,0,0);
00968 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
00969 ++j;
00970 was_off = 0;
00971 sx = x;
00972 sy = y;
00973 } else {
00974 if (!(flags & 1)) {
00975 if (was_off)
00976 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
00977 cx = x;
00978 cy = y;
00979 was_off = 1;
00980 } else {
00981 if (was_off)
00982 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
00983 else
00984 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
00985 was_off = 0;
00986 }
00987 }
00988 }
00989 if (i != 0) {
00990 if (was_off)
00991 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
00992 else
00993 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
00994 }
00995 } else if (numberOfContours == -1) {
00996
00997 int more = 1;
00998 stbtt_uint8 *comp = data + g + 10;
00999 num_vertices = 0;
01000 vertices = 0;
01001 while (more) {
01002 stbtt_uint16 flags, gidx;
01003 int comp_num_verts = 0, i;
01004 stbtt_vertex *comp_verts = 0, *tmp = 0;
01005 float mtx[6] = {1,0,0,1,0,0}, m, n;
01006
01007 flags = ttSHORT(comp); comp+=2;
01008 gidx = ttSHORT(comp); comp+=2;
01009
01010 if (flags & 2) {
01011 if (flags & 1) {
01012 mtx[4] = ttSHORT(comp); comp+=2;
01013 mtx[5] = ttSHORT(comp); comp+=2;
01014 } else {
01015 mtx[4] = ttCHAR(comp); comp+=1;
01016 mtx[5] = ttCHAR(comp); comp+=1;
01017 }
01018 }
01019 else {
01020
01021 STBTT_assert(0);
01022 }
01023 if (flags & (1<<3)) {
01024 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
01025 mtx[1] = mtx[2] = 0;
01026 } else if (flags & (1<<6)) {
01027 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
01028 mtx[1] = mtx[2] = 0;
01029 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
01030 } else if (flags & (1<<7)) {
01031 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
01032 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
01033 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
01034 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
01035 }
01036
01037
01038 m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
01039 n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
01040
01041
01042 comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
01043 if (comp_num_verts > 0) {
01044
01045 for (i = 0; i < comp_num_verts; ++i) {
01046 stbtt_vertex* v = &comp_verts[i];
01047 stbtt_vertex_type x,y;
01048 x=v->x; y=v->y;
01049 v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
01050 v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
01051 x=v->cx; y=v->cy;
01052 v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
01053 v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
01054 }
01055
01056 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
01057 if (!tmp) {
01058 if (vertices) STBTT_free(vertices, info->userdata);
01059 if (comp_verts) STBTT_free(comp_verts, info->userdata);
01060 return 0;
01061 }
01062 if (num_vertices > 0) memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
01063 memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
01064 if (vertices) STBTT_free(vertices, info->userdata);
01065 vertices = tmp;
01066 STBTT_free(comp_verts, info->userdata);
01067 num_vertices += comp_num_verts;
01068 }
01069
01070 more = flags & (1<<5);
01071 }
01072 } else if (numberOfContours < 0) {
01073
01074 STBTT_assert(0);
01075 } else {
01076
01077 }
01078
01079 *pvertices = vertices;
01080 return num_vertices;
01081 }
01082
01083 void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
01084 {
01085 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
01086 if (glyph_index < numOfLongHorMetrics) {
01087 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
01088 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
01089 } else {
01090 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
01091 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
01092 }
01093 }
01094
01095 int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
01096 {
01097 return 0;
01098 }
01099
01100 int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
01101 {
01102 return 0;
01103 }
01104
01105 void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
01106 {
01107 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
01108 }
01109
01110 void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
01111 {
01112 if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
01113 if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
01114 if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
01115 }
01116
01117 float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
01118 {
01119 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
01120 return (float) height / fheight;
01121 }
01122
01123 void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
01124 {
01125 STBTT_free(v, info->userdata);
01126 }
01127
01129
01130
01131
01132
01133 void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
01134 {
01135 int x0,y0,x1,y1;
01136 if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1))
01137 x0=y0=x1=y1=0;
01138
01139 if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x);
01140 if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y);
01141 if (ix1) *ix1 = STBTT_iceil (x1 * scale_x);
01142 if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y);
01143 }
01144
01145 void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
01146 {
01147 stbtt_GetGlyphBitmapBox(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y, ix0,iy0,ix1,iy1);
01148 }
01149
01150 typedef struct stbtt__edge {
01151 float x0,y0, x1,y1;
01152 int invert;
01153 } stbtt__edge;
01154
01155 typedef struct stbtt__active_edge
01156 {
01157 int x,dx;
01158 float ey;
01159 struct stbtt__active_edge *next;
01160 int valid;
01161 } stbtt__active_edge;
01162
01163 #define FIXSHIFT 10
01164 #define FIX (1 << FIXSHIFT)
01165 #define FIXMASK (FIX-1)
01166
01167 static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata)
01168 {
01169 stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata);
01170 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
01171 STBTT_assert(e->y0 <= start_point);
01172 if (!z) return z;
01173
01174 if (dxdy < 0)
01175 z->dx = -STBTT_ifloor(FIX * -dxdy);
01176 else
01177 z->dx = STBTT_ifloor(FIX * dxdy);
01178 z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
01179 z->x -= off_x * FIX;
01180 z->ey = e->y1;
01181 z->next = 0;
01182 z->valid = e->invert ? 1 : -1;
01183 return z;
01184 }
01185
01186
01187
01188
01189 static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
01190 {
01191
01192 int x0=0, w=0;
01193
01194 while (e) {
01195 if (w == 0) {
01196
01197 x0 = e->x; w += e->valid;
01198 } else {
01199 int x1 = e->x; w += e->valid;
01200
01201 if (w == 0) {
01202 int i = x0 >> FIXSHIFT;
01203 int j = x1 >> FIXSHIFT;
01204
01205 if (i < len && j >= 0) {
01206 if (i == j) {
01207
01208 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
01209 } else {
01210 if (i >= 0)
01211 scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
01212 else
01213 i = -1;
01214
01215 if (j < len)
01216 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
01217 else
01218 j = len;
01219
01220 for (++i; i < j; ++i)
01221 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
01222 }
01223 }
01224 }
01225 }
01226
01227 e = e->next;
01228 }
01229 }
01230
01231 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
01232 {
01233 stbtt__active_edge *active = NULL;
01234 int y,j=0;
01235 int max_weight = (255 / vsubsample);
01236 int s;
01237 unsigned char scanline_data[512], *scanline;
01238
01239 if (result->w > 512)
01240 scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
01241 else
01242 scanline = scanline_data;
01243
01244 y = off_y * vsubsample;
01245 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
01246
01247 while (j < result->h) {
01248 STBTT_memset(scanline, 0, result->w);
01249 for (s=0; s < vsubsample; ++s) {
01250
01251 float scan_y = y + 0.5f;
01252 stbtt__active_edge **step = &active;
01253
01254
01255
01256 while (*step) {
01257 stbtt__active_edge * z = *step;
01258 if (z->ey <= scan_y) {
01259 *step = z->next;
01260 STBTT_assert(z->valid);
01261 z->valid = 0;
01262 STBTT_free(z, userdata);
01263 } else {
01264 z->x += z->dx;
01265 step = &((*step)->next);
01266 }
01267 }
01268
01269
01270 for(;;) {
01271 int changed=0;
01272 step = &active;
01273 while (*step && (*step)->next) {
01274 if ((*step)->x > (*step)->next->x) {
01275 stbtt__active_edge *t = *step;
01276 stbtt__active_edge *q = t->next;
01277
01278 t->next = q->next;
01279 q->next = t;
01280 *step = q;
01281 changed = 1;
01282 }
01283 step = &(*step)->next;
01284 }
01285 if (!changed) break;
01286 }
01287
01288
01289 while (e->y0 <= scan_y) {
01290 if (e->y1 > scan_y) {
01291 stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
01292
01293 if (active == NULL)
01294 active = z;
01295 else if (z->x < active->x) {
01296
01297 z->next = active;
01298 active = z;
01299 } else {
01300
01301 stbtt__active_edge *p = active;
01302 while (p->next && p->next->x < z->x)
01303 p = p->next;
01304
01305 z->next = p->next;
01306 p->next = z;
01307 }
01308 }
01309 ++e;
01310 }
01311
01312
01313 if (active)
01314 stbtt__fill_active_edges(scanline, result->w, active, max_weight);
01315
01316 ++y;
01317 }
01318 STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
01319 ++j;
01320 }
01321
01322 while (active) {
01323 stbtt__active_edge *z = active;
01324 active = active->next;
01325 STBTT_free(z, userdata);
01326 }
01327
01328 if (scanline != scanline_data)
01329 STBTT_free(scanline, userdata);
01330 }
01331
01332 static int stbtt__edge_compare(const void *p, const void *q)
01333 {
01334 stbtt__edge *a = (stbtt__edge *) p;
01335 stbtt__edge *b = (stbtt__edge *) q;
01336
01337 if (a->y0 < b->y0) return -1;
01338 if (a->y0 > b->y0) return 1;
01339 return 0;
01340 }
01341
01342 typedef struct
01343 {
01344 float x,y;
01345 } stbtt__point;
01346
01347 static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, int off_x, int off_y, int invert, void *userdata)
01348 {
01349 float y_scale_inv = invert ? -scale_y : scale_y;
01350 stbtt__edge *e;
01351 int n,i,j,k,m;
01352 int vsubsample = result->h < 8 ? 15 : 5;
01353
01354
01355
01356 n = 0;
01357 for (i=0; i < windings; ++i)
01358 n += wcount[i];
01359
01360 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata);
01361 if (e == 0) return;
01362 n = 0;
01363
01364 m=0;
01365 for (i=0; i < windings; ++i) {
01366 stbtt__point *p = pts + m;
01367 m += wcount[i];
01368 j = wcount[i]-1;
01369 for (k=0; k < wcount[i]; j=k++) {
01370 int a=k,b=j;
01371
01372 if (p[j].y == p[k].y)
01373 continue;
01374
01375 e[n].invert = 0;
01376 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
01377 e[n].invert = 1;
01378 a=j,b=k;
01379 }
01380 e[n].x0 = p[a].x * scale_x;
01381 e[n].y0 = p[a].y * y_scale_inv * vsubsample;
01382 e[n].x1 = p[b].x * scale_x;
01383 e[n].y1 = p[b].y * y_scale_inv * vsubsample;
01384 ++n;
01385 }
01386 }
01387
01388
01389 STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
01390
01391
01392 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
01393
01394 STBTT_free(e, userdata);
01395 }
01396
01397 static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
01398 {
01399 if (!points) return;
01400 points[n].x = x;
01401 points[n].y = y;
01402 }
01403
01404
01405 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)
01406 {
01407
01408 float mx = (x0 + 2*x1 + x2)/4;
01409 float my = (y0 + 2*y1 + y2)/4;
01410
01411 float dx = (x0+x2)/2 - mx;
01412 float dy = (y0+y2)/2 - my;
01413 if (n > 16)
01414 return 1;
01415 if (dx*dx+dy*dy > objspace_flatness_squared) {
01416 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
01417 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
01418 } else {
01419 stbtt__add_point(points, *num_points,x2,y2);
01420 *num_points = *num_points+1;
01421 }
01422 return 1;
01423 }
01424
01425
01426 stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
01427 {
01428 stbtt__point *points=0;
01429 int num_points=0;
01430
01431 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
01432 int i,n=0,start=0, pass;
01433
01434
01435 for (i=0; i < num_verts; ++i)
01436 if (vertices[i].type == STBTT_vmove)
01437 ++n;
01438
01439 *num_contours = n;
01440 if (n == 0) return 0;
01441
01442 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
01443
01444 if (*contour_lengths == 0) {
01445 *num_contours = 0;
01446 return 0;
01447 }
01448
01449
01450 for (pass=0; pass < 2; ++pass) {
01451 float x=0,y=0;
01452 if (pass == 1) {
01453 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
01454 if (points == NULL) goto error;
01455 }
01456 num_points = 0;
01457 n= -1;
01458 for (i=0; i < num_verts; ++i) {
01459 switch (vertices[i].type) {
01460 case STBTT_vmove:
01461
01462 if (n >= 0)
01463 (*contour_lengths)[n] = num_points - start;
01464 ++n;
01465 start = num_points;
01466
01467 x = vertices[i].x, y = vertices[i].y;
01468 stbtt__add_point(points, num_points++, x,y);
01469 break;
01470 case STBTT_vline:
01471 x = vertices[i].x, y = vertices[i].y;
01472 stbtt__add_point(points, num_points++, x, y);
01473 break;
01474 case STBTT_vcurve:
01475 stbtt__tesselate_curve(points, &num_points, x,y,
01476 vertices[i].cx, vertices[i].cy,
01477 vertices[i].x, vertices[i].y,
01478 objspace_flatness_squared, 0);
01479 x = vertices[i].x, y = vertices[i].y;
01480 break;
01481 }
01482 }
01483 (*contour_lengths)[n] = num_points - start;
01484 }
01485
01486 return points;
01487 error:
01488 STBTT_free(points, userdata);
01489 STBTT_free(*contour_lengths, userdata);
01490 *contour_lengths = 0;
01491 *num_contours = 0;
01492 return NULL;
01493 }
01494
01495 void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, int x_off, int y_off, int invert, void *userdata)
01496 {
01497 float scale = scale_x > scale_y ? scale_y : scale_x;
01498 int winding_count, *winding_lengths;
01499 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
01500 if (windings) {
01501 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, x_off, y_off, invert, userdata);
01502 STBTT_free(winding_lengths, userdata);
01503 STBTT_free(windings, userdata);
01504 }
01505 }
01506
01507 void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
01508 {
01509 STBTT_free(bitmap, userdata);
01510 }
01511
01512 unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
01513 {
01514 int ix0,iy0,ix1,iy1;
01515 stbtt__bitmap gbm;
01516 stbtt_vertex *vertices;
01517 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
01518
01519 if (scale_x == 0) scale_x = scale_y;
01520 if (scale_y == 0) {
01521 if (scale_x == 0) return NULL;
01522 scale_y = scale_x;
01523 }
01524
01525 stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1);
01526
01527
01528 gbm.w = (ix1 - ix0);
01529 gbm.h = (iy1 - iy0);
01530 gbm.pixels = NULL;
01531
01532 if (width ) *width = gbm.w;
01533 if (height) *height = gbm.h;
01534 if (xoff ) *xoff = ix0;
01535 if (yoff ) *yoff = iy0;
01536
01537 if (gbm.w && gbm.h) {
01538 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
01539 if (gbm.pixels) {
01540 gbm.stride = gbm.w;
01541
01542 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0, iy0, 1, info->userdata);
01543 }
01544 }
01545 STBTT_free(vertices, info->userdata);
01546 return gbm.pixels;
01547 }
01548
01549 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)
01550 {
01551 int ix0,iy0;
01552 stbtt_vertex *vertices;
01553 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
01554 stbtt__bitmap gbm;
01555
01556 stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,0,0);
01557 gbm.pixels = output;
01558 gbm.w = out_w;
01559 gbm.h = out_h;
01560 gbm.stride = out_stride;
01561
01562 if (gbm.w && gbm.h)
01563 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, ix0,iy0, 1, info->userdata);
01564
01565 STBTT_free(vertices, info->userdata);
01566 }
01567
01568 unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
01569 {
01570 return stbtt_GetGlyphBitmap(info, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
01571 }
01572
01573 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)
01574 {
01575 stbtt_MakeGlyphBitmap(info, output, out_w, out_h, out_stride, scale_x, scale_y, stbtt_FindGlyphIndex(info,codepoint));
01576 }
01577
01579
01580
01581
01582
01583
01584 extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
01585 float pixel_height,
01586 unsigned char *pixels, int pw, int ph,
01587 int first_char, int num_chars,
01588 stbtt_bakedchar *chardata)
01589 {
01590 float scale;
01591 int x,y,bottom_y, i;
01592 stbtt_fontinfo f;
01593 stbtt_InitFont(&f, data, offset);
01594 STBTT_memset(pixels, 0, pw*ph);
01595 x=y=1;
01596 bottom_y = 1;
01597
01598 scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
01599
01600 for (i=0; i < num_chars; ++i) {
01601 int advance, lsb, x0,y0,x1,y1,gw,gh;
01602 int g = stbtt_FindGlyphIndex(&f, first_char + i);
01603 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
01604 stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
01605 gw = x1-x0;
01606 gh = y1-y0;
01607 if (x + gw + 1 >= pw)
01608 y = bottom_y, x = 1;
01609 if (y + gh + 1 >= ph)
01610 return -i;
01611 STBTT_assert(x+gw < pw);
01612 STBTT_assert(y+gh < ph);
01613 stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
01614 chardata[i].x0 = (stbtt_int16) x;
01615 chardata[i].y0 = (stbtt_int16) y;
01616 chardata[i].x1 = (stbtt_int16) (x + gw);
01617 chardata[i].y1 = (stbtt_int16) (y + gh);
01618 chardata[i].xadvance = scale * advance;
01619 chardata[i].xoff = (float) x0;
01620 chardata[i].yoff = (float) y0;
01621 x = x + gw + 2;
01622 if (y+gh+2 > bottom_y)
01623 bottom_y = y+gh+2;
01624 }
01625 return bottom_y;
01626 }
01627
01628 void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
01629 {
01630 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
01631 float ipw = 1.0f / pw, iph = 1.0f / ph;
01632 stbtt_bakedchar *b = chardata + char_index;
01633 int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5);
01634 int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5);
01635
01636 q->x0 = round_x + d3d_bias;
01637 q->y0 = round_y + d3d_bias;
01638 q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
01639 q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
01640
01641 q->s0 = b->x0 * ipw;
01642 q->t0 = b->y0 * ipw;
01643 q->s1 = b->x1 * iph;
01644 q->t1 = b->y1 * iph;
01645
01646 *xpos += b->xadvance;
01647 }
01648
01650
01651
01652
01653
01654
01655 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
01656 {
01657 stbtt_int32 i=0;
01658
01659
01660 while (len2) {
01661 stbtt_uint16 ch = s2[0]*256 + s2[1];
01662 if (ch < 0x80) {
01663 if (i >= len1) return -1;
01664 if (s1[i++] != ch) return -1;
01665 } else if (ch < 0x800) {
01666 if (i+1 >= len1) return -1;
01667 if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
01668 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
01669 } else if (ch >= 0xd800 && ch < 0xdc00) {
01670 stbtt_uint32 c;
01671 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
01672 if (i+3 >= len1) return -1;
01673 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
01674 if (s1[i++] != 0xf0 + (c >> 18)) return -1;
01675 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
01676 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
01677 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
01678 s2 += 2;
01679 len2 -= 2;
01680 } else if (ch >= 0xdc00 && ch < 0xe000) {
01681 return -1;
01682 } else {
01683 if (i+2 >= len1) return -1;
01684 if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
01685 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
01686 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
01687 }
01688 s2 += 2;
01689 len2 -= 2;
01690 }
01691 return i;
01692 }
01693
01694 int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
01695 {
01696 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
01697 }
01698
01699
01700
01701 char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
01702 {
01703 stbtt_int32 i,count,stringOffset;
01704 stbtt_uint8 *fc = font->data;
01705 stbtt_uint32 offset = font->fontstart;
01706 stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
01707 if (!nm) return NULL;
01708
01709 count = ttUSHORT(fc+nm+2);
01710 stringOffset = nm + ttUSHORT(fc+nm+4);
01711 for (i=0; i < count; ++i) {
01712 stbtt_uint32 loc = nm + 6 + 12 * i;
01713 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
01714 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
01715 *length = ttUSHORT(fc+loc+8);
01716 return (char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
01717 }
01718 }
01719 return NULL;
01720 }
01721
01722 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
01723 {
01724 stbtt_int32 i;
01725 stbtt_int32 count = ttUSHORT(fc+nm+2);
01726 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
01727
01728 for (i=0; i < count; ++i) {
01729 stbtt_uint32 loc = nm + 6 + 12 * i;
01730 stbtt_int32 id = ttUSHORT(fc+loc+6);
01731 if (id == target_id) {
01732
01733 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
01734
01735
01736 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
01737 stbtt_int32 slen = ttUSHORT(fc+loc+8), off = ttUSHORT(fc+loc+10);
01738
01739
01740 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
01741 if (matchlen >= 0) {
01742
01743 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) {
01744 stbtt_int32 slen = ttUSHORT(fc+loc+12+8), off = ttUSHORT(fc+loc+12+10);
01745 if (slen == 0) {
01746 if (matchlen == nlen)
01747 return 1;
01748 } else if (matchlen < nlen && name[matchlen] == ' ') {
01749 ++matchlen;
01750 if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
01751 return 1;
01752 }
01753 } else {
01754
01755 if (matchlen == nlen)
01756 return 1;
01757 }
01758 }
01759 }
01760
01761
01762 }
01763 }
01764 return 0;
01765 }
01766
01767 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
01768 {
01769 stbtt_int32 nlen = STBTT_strlen((char *) name);
01770 stbtt_uint32 nm,hd;
01771 if (!stbtt__isfont(fc+offset)) return 0;
01772
01773
01774 if (flags) {
01775 hd = stbtt__find_table(fc, offset, "head");
01776 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
01777 }
01778
01779 nm = stbtt__find_table(fc, offset, "name");
01780 if (!nm) return 0;
01781
01782 if (flags) {
01783
01784 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
01785 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
01786 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
01787 } else {
01788 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
01789 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
01790 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
01791 }
01792
01793 return 0;
01794 }
01795
01796 int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags)
01797 {
01798 stbtt_int32 i;
01799 for (i=0;;++i) {
01800 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
01801 if (off < 0) return off;
01802 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
01803 return off;
01804 }
01805 }
01806
01807 #endif // STB_TRUETYPE_IMPLEMENTATION