275 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
278 unsigned char ttf_buffer[1<<20];
279 unsigned char temp_bitmap[512*512];
284 void my_stbtt_initfont(
void)
286 fread(ttf_buffer, 1, 1<<20, fopen(
"c:/windows/fonts/times.ttf",
"rb"));
289 glGenTextures(1, &ftex);
290 glBindTexture(GL_TEXTURE_2D, ftex);
291 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
293 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
296 void my_stbtt_print(
float x,
float y,
char *text)
299 glEnable(GL_TEXTURE_2D);
300 glBindTexture(GL_TEXTURE_2D, ftex);
303 if (*text >= 32 && *text < 128) {
306 glTexCoord2f(q.
s0,q.
t1); glVertex2f(q.
x0,q.
y0);
307 glTexCoord2f(q.
s1,q.
t1); glVertex2f(q.
x1,q.
y0);
308 glTexCoord2f(q.
s1,q.
t0); glVertex2f(q.
x1,q.
y1);
309 glTexCoord2f(q.
s0,q.
t0); glVertex2f(q.
x0,q.
y1);
324 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
327 char ttf_buffer[1<<25];
329 int main(
int argc,
char **argv)
332 unsigned char *bitmap;
333 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) :
'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
335 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] :
"c:/windows/fonts/arialbd.ttf",
"rb"));
340 for (j=0; j < h; ++j) {
341 for (i=0; i < w; ++i)
342 putchar(
" .:ioVM@"[bitmap[j*w+i]>>5]);
368 unsigned char screen[20][79];
370 int main(
int arg,
char **argv)
373 int i,j,ascent,baseline,ch=0;
375 char *text =
"Heljo World!";
377 fread(buffer, 1, 1000000, fopen(
"c:/windows/fonts/arialbd.ttf",
"rb"));
382 baseline = (
int) (ascent*scale);
385 int advance,lsb,x0,y0,x1,y1;
386 float x_shift = xpos - (float) floor(xpos);
394 xpos += (advance * scale);
400 for (j=0; j < 20; ++j) {
401 for (i=0; i < 78; ++i)
402 putchar(
" .:ioVM@"[screen[j][i]>>5]);
420 #ifdef STB_TRUETYPE_IMPLEMENTATION
423 typedef unsigned char stbtt_uint8;
424 typedef signed char stbtt_int8;
425 typedef unsigned short stbtt_uint16;
426 typedef signed short stbtt_int16;
427 typedef unsigned int stbtt_uint32;
428 typedef signed int stbtt_int32;
431 typedef char stbtt__check_size32[
sizeof(stbtt_int32)==4 ? 1 : -1];
432 typedef char stbtt__check_size16[
sizeof(stbtt_int16)==2 ? 1 : -1];
437 #define STBTT_ifloor(x) ((int) floor(x))
438 #define STBTT_iceil(x) ((int) ceil(x))
443 #define STBTT_sqrt(x) sqrt(x)
444 #define STBTT_pow(x,y) pow(x,y)
449 #define STBTT_fmod(x,y) fmod(x,y)
454 #define STBTT_cos(x) cos(x)
455 #define STBTT_acos(x) acos(x)
460 #define STBTT_fabs(x) fabs(x)
466 #define STBTT_malloc(x,u) ((void)(u),malloc(x))
467 #define STBTT_free(x,u) ((void)(u),free(x))
472 #define STBTT_assert(x) assert(x)
477 #define STBTT_strlen(x) strlen(x)
482 #define STBTT_memcpy memcpy
483 #define STBTT_memset memset
494 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
495 #define __STB_INCLUDE_STB_TRUETYPE_H__
498 #define STBTT_DEF static
500 #define STBTT_DEF extern
524 unsigned short x0,y0,x1,
y1;
530 unsigned char *pixels,
int pw,
int ph,
531 int first_char,
int num_chars,
546 float *xpos,
float *ypos,
548 int opengl_fillrule);
577 #ifndef STB_RECT_PACK_VERSION
595 #define STBTT_POINT_SIZE(x) (-(x))
598 int first_unicode_char_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range);
646 float *xpos,
float *ypos,
648 int align_to_integer);
796 #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
805 #ifndef stbtt_vertex // you can predefine this to use different values
807 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
864 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);
885 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);
899 float flatness_in_pixels,
902 float scale_x,
float scale_y,
903 float shift_x,
float shift_y,
904 int x_off,
int y_off,
915 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);
916 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);
993 #define STBTT_MACSTYLE_DONTCARE 0
994 #define STBTT_MACSTYLE_BOLD 1
995 #define STBTT_MACSTYLE_ITALIC 2
996 #define STBTT_MACSTYLE_UNDERSCORE 4
997 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
1064 #endif // __STB_INCLUDE_STB_TRUETYPE_H__
1073 #ifdef STB_TRUETYPE_IMPLEMENTATION
1075 #ifndef STBTT_MAX_OVERSAMPLE
1076 #define STBTT_MAX_OVERSAMPLE 8
1079 #if STBTT_MAX_OVERSAMPLE > 255
1080 #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
1083 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
1085 #ifndef STBTT_RASTERIZER_VERSION
1086 #define STBTT_RASTERIZER_VERSION 2
1090 #define STBTT__NOTUSED(v) (void)(v)
1092 #define STBTT__NOTUSED(v) (void)sizeof(v)
1100 static stbtt_uint8 stbtt__buf_get8(
stbtt__buf *b)
1107 static stbtt_uint8 stbtt__buf_peek8(
stbtt__buf *b)
1114 static void stbtt__buf_seek(
stbtt__buf *b,
int o)
1116 STBTT_assert(!(o > b->
size || o < 0));
1120 static void stbtt__buf_skip(
stbtt__buf *b,
int o)
1122 stbtt__buf_seek(b, b->
cursor + o);
1125 static stbtt_uint32 stbtt__buf_get(
stbtt__buf *b,
int n)
1129 STBTT_assert(n >= 1 && n <= 4);
1130 for (i = 0; i < n; i++)
1131 v = (v << 8) | stbtt__buf_get8(b);
1138 STBTT_assert(size < 0x40000000);
1139 r.
data = (stbtt_uint8*) p;
1145 #define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
1146 #define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
1151 if (o < 0 || s < 0 || o > b->
size || s > b->
size - o)
return r;
1159 int count, start, offsize;
1161 count = stbtt__buf_get16(b);
1163 offsize = stbtt__buf_get8(b);
1164 STBTT_assert(offsize >= 1 && offsize <= 4);
1165 stbtt__buf_skip(b, offsize * count);
1166 stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
1168 return stbtt__buf_range(b, start, b->
cursor - start);
1171 static stbtt_uint32 stbtt__cff_int(
stbtt__buf *b)
1173 int b0 = stbtt__buf_get8(b);
1174 if (b0 >= 32 && b0 <= 246)
return b0 - 139;
1175 else if (b0 >= 247 && b0 <= 250)
return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
1176 else if (b0 >= 251 && b0 <= 254)
return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
1177 else if (b0 == 28)
return stbtt__buf_get16(b);
1178 else if (b0 == 29)
return stbtt__buf_get32(b);
1183 static void stbtt__cff_skip_operand(
stbtt__buf *b) {
1184 int v, b0 = stbtt__buf_peek8(b);
1185 STBTT_assert(b0 >= 28);
1187 stbtt__buf_skip(b, 1);
1189 v = stbtt__buf_get8(b);
1190 if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
1200 stbtt__buf_seek(b, 0);
1202 int start = b->
cursor, end, op;
1203 while (stbtt__buf_peek8(b) >= 28)
1204 stbtt__cff_skip_operand(b);
1206 op = stbtt__buf_get8(b);
1207 if (op == 12) op = stbtt__buf_get8(b) | 0x100;
1208 if (op == key)
return stbtt__buf_range(b, start, end-start);
1210 return stbtt__buf_range(b, 0, 0);
1213 static void stbtt__dict_get_ints(
stbtt__buf *b,
int key,
int outcount, stbtt_uint32 *out)
1216 stbtt__buf operands = stbtt__dict_get(b, key);
1217 for (i = 0; i < outcount && operands.
cursor < operands.
size; i++)
1218 out[i] = stbtt__cff_int(&operands);
1221 static int stbtt__cff_index_count(
stbtt__buf *b)
1223 stbtt__buf_seek(b, 0);
1224 return stbtt__buf_get16(b);
1229 int count, offsize, start, end;
1230 stbtt__buf_seek(&b, 0);
1231 count = stbtt__buf_get16(&b);
1232 offsize = stbtt__buf_get8(&b);
1233 STBTT_assert(i >= 0 && i < count);
1234 STBTT_assert(offsize >= 1 && offsize <= 4);
1235 stbtt__buf_skip(&b, i*offsize);
1236 start = stbtt__buf_get(&b, offsize);
1237 end = stbtt__buf_get(&b, offsize);
1238 return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
1249 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
1250 #define ttCHAR(p) (* (stbtt_int8 *) (p))
1251 #define ttFixed(p) ttLONG(p)
1253 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) {
return p[0]*256 + p[1]; }
1254 static stbtt_int16 ttSHORT(stbtt_uint8 *p) {
return p[0]*256 + p[1]; }
1255 static stbtt_uint32 ttULONG(stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1256 static stbtt_int32 ttLONG(stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
1258 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
1259 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
1261 static int stbtt__isfont(stbtt_uint8 *font)
1264 if (stbtt_tag4(font,
'1',0,0,0))
return 1;
1265 if (stbtt_tag(font,
"typ1"))
return 1;
1266 if (stbtt_tag(font,
"OTTO"))
return 1;
1267 if (stbtt_tag4(font, 0,1,0,0))
return 1;
1268 if (stbtt_tag(font,
"true"))
return 1;
1273 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart,
const char *tag)
1275 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
1276 stbtt_uint32 tabledir = fontstart + 12;
1278 for (i=0; i < num_tables; ++i) {
1279 stbtt_uint32 loc = tabledir + 16*i;
1280 if (stbtt_tag(data+loc+0, tag))
1281 return ttULONG(data+loc+8);
1286 static int stbtt_GetFontOffsetForIndex_internal(
unsigned char *font_collection,
int index)
1289 if (stbtt__isfont(font_collection))
1290 return index == 0 ? 0 : -1;
1293 if (stbtt_tag(font_collection,
"ttcf")) {
1295 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1296 stbtt_int32 n = ttLONG(font_collection+8);
1299 return ttULONG(font_collection+12+index*4);
1305 static int stbtt_GetNumberOfFonts_internal(
unsigned char *font_collection)
1308 if (stbtt__isfont(font_collection))
1312 if (stbtt_tag(font_collection,
"ttcf")) {
1314 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1315 return ttLONG(font_collection+8);
1323 stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
1325 stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
1326 if (!private_loc[1] || !private_loc[0])
return stbtt__new_buf(NULL, 0);
1327 pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
1328 stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
1329 if (!subrsoff)
return stbtt__new_buf(NULL, 0);
1330 stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
1331 return stbtt__cff_get_index(&cff);
1334 static int stbtt_InitFont_internal(
stbtt_fontinfo *info,
unsigned char *data,
int fontstart)
1336 stbtt_uint32 cmap, t;
1337 stbtt_int32 i,numTables;
1341 info->
cff = stbtt__new_buf(NULL, 0);
1343 cmap = stbtt__find_table(data, fontstart,
"cmap");
1344 info->
loca = stbtt__find_table(data, fontstart,
"loca");
1345 info->
head = stbtt__find_table(data, fontstart,
"head");
1346 info->
glyf = stbtt__find_table(data, fontstart,
"glyf");
1347 info->
hhea = stbtt__find_table(data, fontstart,
"hhea");
1348 info->
hmtx = stbtt__find_table(data, fontstart,
"hmtx");
1349 info->
kern = stbtt__find_table(data, fontstart,
"kern");
1350 info->
gpos = stbtt__find_table(data, fontstart,
"GPOS");
1352 if (!cmap || !info->
head || !info->
hhea || !info->
hmtx)
1356 if (!info->
loca)
return 0;
1360 stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
1363 cff = stbtt__find_table(data, fontstart,
"CFF ");
1366 info->
fontdicts = stbtt__new_buf(NULL, 0);
1367 info->
fdselect = stbtt__new_buf(NULL, 0);
1370 info->
cff = stbtt__new_buf(data+cff, 512*1024*1024);
1374 stbtt__buf_skip(&b, 2);
1375 stbtt__buf_seek(&b, stbtt__buf_get8(&b));
1379 stbtt__cff_get_index(&b);
1380 topdictidx = stbtt__cff_get_index(&b);
1381 topdict = stbtt__cff_index_get(topdictidx, 0);
1382 stbtt__cff_get_index(&b);
1383 info->
gsubrs = stbtt__cff_get_index(&b);
1385 stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
1386 stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
1387 stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
1388 stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
1389 info->
subrs = stbtt__get_subrs(b, topdict);
1392 if (cstype != 2)
return 0;
1393 if (charstrings == 0)
return 0;
1397 if (!fdselectoff)
return 0;
1398 stbtt__buf_seek(&b, fdarrayoff);
1399 info->
fontdicts = stbtt__cff_get_index(&b);
1400 info->
fdselect = stbtt__buf_range(&b, fdselectoff, b.
size-fdselectoff);
1403 stbtt__buf_seek(&b, charstrings);
1407 t = stbtt__find_table(data, fontstart,
"maxp");
1416 numTables = ttUSHORT(data + cmap + 2);
1418 for (i=0; i < numTables; ++i) {
1419 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1421 switch(ttUSHORT(data+encoding_record)) {
1423 switch (ttUSHORT(data+encoding_record+2)) {
1427 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1434 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1447 stbtt_uint8 *data = info->
data;
1448 stbtt_uint32 index_map = info->
index_map;
1450 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1452 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1453 if (unicode_codepoint < bytes-6)
1454 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1456 }
else if (format == 6) {
1457 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1458 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1459 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1460 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1462 }
else if (format == 2) {
1465 }
else if (format == 4) {
1466 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1467 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1468 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1469 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1472 stbtt_uint32 endCount = index_map + 14;
1473 stbtt_uint32 search = endCount;
1475 if (unicode_codepoint > 0xffff)
1480 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1481 search += rangeShift*2;
1485 while (entrySelector) {
1488 end = ttUSHORT(data + search + searchRange*2);
1489 if (unicode_codepoint > end)
1490 search += searchRange*2;
1496 stbtt_uint16
offset, start;
1497 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
1499 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1500 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1501 if (unicode_codepoint < start)
1504 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1506 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1508 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1510 }
else if (format == 12 || format == 13) {
1511 stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1512 stbtt_int32 low,high;
1513 low = 0; high = (stbtt_int32)ngroups;
1515 while (low < high) {
1516 stbtt_int32 mid = low + ((high-low) >> 1);
1517 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1518 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1519 if ((stbtt_uint32) unicode_codepoint < start_char)
1521 else if ((stbtt_uint32) unicode_codepoint > end_char)
1524 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1526 return start_glyph + unicode_codepoint-start_char;
1543 static void stbtt_setvertex(
stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1546 v->
x = (stbtt_int16) x;
1547 v->
y = (stbtt_int16) y;
1548 v->
cx = (stbtt_int16) cx;
1549 v->
cy = (stbtt_int16) cy;
1552 static int stbtt__GetGlyfOffset(
const stbtt_fontinfo *info,
int glyph_index)
1556 STBTT_assert(!info->
cff.
size);
1558 if (glyph_index >= info->
numGlyphs)
return -1;
1562 g1 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2) * 2;
1563 g2 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2 + 2) * 2;
1565 g1 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4);
1566 g2 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4 + 4);
1569 return g1==g2 ? -1 : g1;
1572 static int stbtt__GetGlyphInfoT2(
const stbtt_fontinfo *info,
int glyph_index,
int *x0,
int *y0,
int *x1,
int *y1);
1577 stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
1579 int g = stbtt__GetGlyfOffset(info, glyph_index);
1580 if (g < 0)
return 0;
1582 if (x0) *x0 = ttSHORT(info->
data + g + 2);
1583 if (y0) *y0 = ttSHORT(info->
data + g + 4);
1584 if (x1) *x1 = ttSHORT(info->
data + g + 6);
1585 if (y1) *y1 = ttSHORT(info->
data + g + 8);
1597 stbtt_int16 numberOfContours;
1600 return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
1601 g = stbtt__GetGlyfOffset(info, glyph_index);
1602 if (g < 0)
return 1;
1603 numberOfContours = ttSHORT(info->
data + g);
1604 return numberOfContours == 0;
1607 static int stbtt__close_shape(
stbtt_vertex *vertices,
int num_vertices,
int was_off,
int start_off,
1608 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1612 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1613 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, sx,sy,scx,scy);
1616 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve,sx,sy,cx,cy);
1618 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline,sx,sy,0,0);
1620 return num_vertices;
1625 stbtt_int16 numberOfContours;
1626 stbtt_uint8 *endPtsOfContours;
1627 stbtt_uint8 *data = info->
data;
1630 int g = stbtt__GetGlyfOffset(info, glyph_index);
1634 if (g < 0)
return 0;
1636 numberOfContours = ttSHORT(data + g);
1638 if (numberOfContours > 0) {
1639 stbtt_uint8 flags=0,flagcount;
1640 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1641 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1642 stbtt_uint8 *points;
1643 endPtsOfContours = (data + g + 10);
1644 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1645 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1647 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1649 m = n + 2*numberOfContours;
1665 for (i=0; i < n; ++i) {
1666 if (flagcount == 0) {
1669 flagcount = *points++;
1672 vertices[off+i].
type = flags;
1677 for (i=0; i < n; ++i) {
1678 flags = vertices[off+i].
type;
1680 stbtt_int16 dx = *points++;
1681 x += (flags & 16) ? dx : -dx;
1683 if (!(flags & 16)) {
1684 x = x + (stbtt_int16) (points[0]*256 + points[1]);
1688 vertices[off+i].
x = (stbtt_int16) x;
1693 for (i=0; i < n; ++i) {
1694 flags = vertices[off+i].
type;
1696 stbtt_int16 dy = *points++;
1697 y += (flags & 32) ? dy : -dy;
1699 if (!(flags & 32)) {
1700 y = y + (stbtt_int16) (points[0]*256 + points[1]);
1704 vertices[off+i].
y = (stbtt_int16) y;
1709 sx = sy = cx = cy = scx = scy = 0;
1710 for (i=0; i < n; ++i) {
1711 flags = vertices[off+i].
type;
1712 x = (stbtt_int16) vertices[off+i].x;
1713 y = (stbtt_int16) vertices[off+i].y;
1715 if (next_move == i) {
1717 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1720 start_off = !(flags & 1);
1726 if (!(vertices[off+i+1].type & 1)) {
1728 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1729 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1732 sx = (stbtt_int32) vertices[off+i+1].x;
1733 sy = (stbtt_int32) vertices[off+i+1].y;
1740 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vmove,sx,sy,0,0);
1742 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1747 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1753 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, x,y, cx, cy);
1755 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline, x,y,0,0);
1760 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1761 }
else if (numberOfContours == -1) {
1764 stbtt_uint8 *comp = data + g + 10;
1768 stbtt_uint16 flags, gidx;
1769 int comp_num_verts = 0, i;
1771 float mtx[6] = {1,0,0,1,0,0}, m, n;
1773 flags = ttSHORT(comp); comp+=2;
1774 gidx = ttSHORT(comp); comp+=2;
1778 mtx[4] = ttSHORT(comp); comp+=2;
1779 mtx[5] = ttSHORT(comp); comp+=2;
1781 mtx[4] = ttCHAR(comp); comp+=1;
1782 mtx[5] = ttCHAR(comp); comp+=1;
1789 if (flags & (1<<3)) {
1790 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1791 mtx[1] = mtx[2] = 0;
1792 }
else if (flags & (1<<6)) {
1793 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1794 mtx[1] = mtx[2] = 0;
1795 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1796 }
else if (flags & (1<<7)) {
1797 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1798 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1799 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1800 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1804 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1805 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1809 if (comp_num_verts > 0) {
1811 for (i = 0; i < comp_num_verts; ++i) {
1824 if (vertices) STBTT_free(vertices, info->
userdata);
1825 if (comp_verts) STBTT_free(comp_verts, info->
userdata);
1828 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*
sizeof(
stbtt_vertex));
1829 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*
sizeof(
stbtt_vertex));
1830 if (vertices) STBTT_free(vertices, info->
userdata);
1832 STBTT_free(comp_verts, info->
userdata);
1833 num_vertices += comp_num_verts;
1836 more = flags & (1<<5);
1838 }
else if (numberOfContours < 0) {
1845 *pvertices = vertices;
1846 return num_vertices;
1853 float first_x, first_y;
1855 stbtt_int32 min_x, max_x, min_y, max_y;
1861 #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
1863 static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
1865 if (x > c->max_x || !c->started) c->max_x = x;
1866 if (y > c->max_y || !c->started) c->max_y = y;
1867 if (x < c->min_x || !c->started) c->min_x = x;
1868 if (y < c->min_y || !c->started) c->min_y = y;
1872 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)
1875 stbtt__track_vertex(c, x, y);
1877 stbtt__track_vertex(c, cx, cy);
1878 stbtt__track_vertex(c, cx1, cy1);
1881 stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
1882 c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
1883 c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
1888 static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
1890 if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
1891 stbtt__csctx_v(ctx,
STBTT_vline, (
int)ctx->first_x, (
int)ctx->first_y, 0, 0, 0, 0);
1894 static void stbtt__csctx_rmove_to(stbtt__csctx *ctx,
float dx,
float dy)
1896 stbtt__csctx_close_shape(ctx);
1897 ctx->first_x = ctx->x = ctx->x + dx;
1898 ctx->first_y = ctx->y = ctx->y + dy;
1899 stbtt__csctx_v(ctx,
STBTT_vmove, (
int)ctx->x, (
int)ctx->y, 0, 0, 0, 0);
1902 static void stbtt__csctx_rline_to(stbtt__csctx *ctx,
float dx,
float dy)
1906 stbtt__csctx_v(ctx,
STBTT_vline, (
int)ctx->x, (
int)ctx->y, 0, 0, 0, 0);
1909 static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx,
float dx1,
float dy1,
float dx2,
float dy2,
float dx3,
float dy3)
1911 float cx1 = ctx->x + dx1;
1912 float cy1 = ctx->y + dy1;
1913 float cx2 = cx1 + dx2;
1914 float cy2 = cy1 + dy2;
1917 stbtt__csctx_v(ctx,
STBTT_vcubic, (
int)ctx->x, (
int)ctx->y, (
int)cx1, (
int)cy1, (
int)cx2, (
int)cy2);
1922 int count = stbtt__cff_index_count(&idx);
1926 else if (count >= 1240)
1929 if (n < 0 || n >= count)
1930 return stbtt__new_buf(NULL, 0);
1931 return stbtt__cff_index_get(idx, n);
1937 int nranges, start, end, v, fmt, fdselector = -1, i;
1939 stbtt__buf_seek(&fdselect, 0);
1940 fmt = stbtt__buf_get8(&fdselect);
1943 stbtt__buf_skip(&fdselect, glyph_index);
1944 fdselector = stbtt__buf_get8(&fdselect);
1945 }
else if (fmt == 3) {
1946 nranges = stbtt__buf_get16(&fdselect);
1947 start = stbtt__buf_get16(&fdselect);
1948 for (i = 0; i < nranges; i++) {
1949 v = stbtt__buf_get8(&fdselect);
1950 end = stbtt__buf_get16(&fdselect);
1951 if (glyph_index >= start && glyph_index < end) {
1958 if (fdselector == -1) stbtt__new_buf(NULL, 0);
1959 return stbtt__get_subrs(info->
cff, stbtt__cff_index_get(info->
fontdicts, fdselector));
1962 static int stbtt__run_charstring(
const stbtt_fontinfo *info,
int glyph_index, stbtt__csctx *c)
1964 int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
1965 int has_subrs = 0, clear_stack;
1970 #define STBTT__CSERR(s) (0)
1973 b = stbtt__cff_index_get(info->
charstrings, glyph_index);
1977 b0 = stbtt__buf_get8(&b);
1983 maskbits += (sp / 2);
1985 stbtt__buf_skip(&b, (maskbits + 7) / 8);
1992 maskbits += (sp / 2);
1997 if (sp < 2)
return STBTT__CSERR(
"rmoveto stack");
1998 stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
2002 if (sp < 1)
return STBTT__CSERR(
"vmoveto stack");
2003 stbtt__csctx_rmove_to(c, 0, s[sp-1]);
2007 if (sp < 1)
return STBTT__CSERR(
"hmoveto stack");
2008 stbtt__csctx_rmove_to(c, s[sp-1], 0);
2012 if (sp < 2)
return STBTT__CSERR(
"rlineto stack");
2013 for (; i + 1 < sp; i += 2)
2014 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2021 if (sp < 1)
return STBTT__CSERR(
"vlineto stack");
2024 if (sp < 1)
return STBTT__CSERR(
"hlineto stack");
2027 stbtt__csctx_rline_to(c, s[i], 0);
2031 stbtt__csctx_rline_to(c, 0, s[i]);
2037 if (sp < 4)
return STBTT__CSERR(
"hvcurveto stack");
2040 if (sp < 4)
return STBTT__CSERR(
"vhcurveto stack");
2042 if (i + 3 >= sp)
break;
2043 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);
2046 if (i + 3 >= sp)
break;
2047 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]);
2053 if (sp < 6)
return STBTT__CSERR(
"rcurveline stack");
2054 for (; i + 5 < sp; i += 6)
2055 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2059 if (sp < 8)
return STBTT__CSERR(
"rcurveline stack");
2060 for (; i + 5 < sp - 2; i += 6)
2061 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2062 if (i + 1 >= sp)
return STBTT__CSERR(
"rcurveline stack");
2063 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2067 if (sp < 8)
return STBTT__CSERR(
"rlinecurve stack");
2068 for (; i + 1 < sp - 6; i += 2)
2069 stbtt__csctx_rline_to(c, s[i], s[i+1]);
2070 if (i + 5 >= sp)
return STBTT__CSERR(
"rlinecurve stack");
2071 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
2076 if (sp < 4)
return STBTT__CSERR(
"(vv|hh)curveto stack");
2078 if (sp & 1) { f = s[i]; i++; }
2079 for (; i + 3 < sp; i += 4) {
2081 stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
2083 stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
2091 subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
2096 if (sp < 1)
return STBTT__CSERR(
"call(g|)subr stack");
2098 if (subr_stack_height >= 10)
return STBTT__CSERR(
"recursion limit");
2099 subr_stack[subr_stack_height++] = b;
2100 b = stbtt__get_subr(b0 == 0x0A ? subrs : info->
gsubrs, v);
2101 if (b.
size == 0)
return STBTT__CSERR(
"subr not found");
2107 if (subr_stack_height <= 0)
return STBTT__CSERR(
"return outside subr");
2108 b = subr_stack[--subr_stack_height];
2113 stbtt__csctx_close_shape(c);
2117 float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
2119 int b1 = stbtt__buf_get8(&b);
2124 if (sp < 7)
return STBTT__CSERR(
"hflex stack");
2132 stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
2133 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
2137 if (sp < 13)
return STBTT__CSERR(
"flex stack");
2151 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2152 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2156 if (sp < 9)
return STBTT__CSERR(
"hflex1 stack");
2166 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
2167 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
2171 if (sp < 11)
return STBTT__CSERR(
"flex1 stack");
2183 dx = dx1+dx2+dx3+dx4+dx5;
2184 dy = dy1+dy2+dy3+dy4+dy5;
2185 if (STBTT_fabs(dx) > STBTT_fabs(dy))
2189 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
2190 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
2194 return STBTT__CSERR(
"unimplemented");
2199 if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
2200 return STBTT__CSERR(
"reserved operator");
2204 f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
2206 stbtt__buf_skip(&b, -1);
2207 f = (float)(stbtt_int16)stbtt__cff_int(&b);
2209 if (sp >= 48)
return STBTT__CSERR(
"push stack overflow");
2214 if (clear_stack) sp = 0;
2216 return STBTT__CSERR(
"no endchar");
2224 stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
2225 stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
2226 if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
2228 output_ctx.pvertices = *pvertices;
2229 if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
2230 STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
2231 return output_ctx.num_vertices;
2238 static int stbtt__GetGlyphInfoT2(
const stbtt_fontinfo *info,
int glyph_index,
int *x0,
int *y0,
int *x1,
int *y1)
2240 stbtt__csctx c = STBTT__CSCTX_INIT(1);
2241 int r = stbtt__run_charstring(info, glyph_index, &c);
2242 if (x0) *x0 = r ? c.min_x : 0;
2243 if (y0) *y0 = r ? c.min_y : 0;
2244 if (x1) *x1 = r ? c.max_x : 0;
2245 if (y1) *y1 = r ? c.max_y : 0;
2246 return r ? c.num_vertices : 0;
2252 return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
2254 return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
2259 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->
data+info->
hhea + 34);
2260 if (glyph_index < numOfLongHorMetrics) {
2261 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*glyph_index);
2262 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*glyph_index + 2);
2264 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*(numOfLongHorMetrics-1));
2265 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
2269 static int stbtt__GetGlyphKernInfoAdvance(
const stbtt_fontinfo *info,
int glyph1,
int glyph2)
2271 stbtt_uint8 *data = info->
data + info->
kern;
2272 stbtt_uint32 needle, straw;
2278 if (ttUSHORT(data+2) < 1)
2280 if (ttUSHORT(data+8) != 1)
2284 r = ttUSHORT(data+10) - 1;
2285 needle = glyph1 << 16 | glyph2;
2288 straw = ttULONG(data+18+(m*6));
2291 else if (needle > straw)
2294 return ttSHORT(data+22+(m*6));
2299 static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable,
int glyph)
2301 stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2302 switch(coverageFormat) {
2304 stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2307 stbtt_int32 l=0, r=glyphCount-1, m;
2308 int straw, needle=glyph;
2310 stbtt_uint8 *glyphArray = coverageTable + 4;
2311 stbtt_uint16 glyphID;
2313 glyphID = ttUSHORT(glyphArray + 2 * m);
2317 else if (needle > straw)
2326 stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2327 stbtt_uint8 *rangeArray = coverageTable + 4;
2330 stbtt_int32 l=0, r=rangeCount-1, m;
2331 int strawStart, strawEnd, needle=glyph;
2333 stbtt_uint8 *rangeRecord;
2335 rangeRecord = rangeArray + 6 * m;
2336 strawStart = ttUSHORT(rangeRecord);
2337 strawEnd = ttUSHORT(rangeRecord + 2);
2338 if (needle < strawStart)
2340 else if (needle > strawEnd)
2343 stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2344 return startCoverageIndex + glyph - strawStart;
2358 static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable,
int glyph)
2360 stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2361 switch(classDefFormat)
2364 stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2365 stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2366 stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
2368 if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2369 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2371 classDefTable = classDef1ValueArray + 2 * glyphCount;
2375 stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2376 stbtt_uint8 *classRangeRecords = classDefTable + 4;
2379 stbtt_int32 l=0, r=classRangeCount-1, m;
2380 int strawStart, strawEnd, needle=glyph;
2382 stbtt_uint8 *classRangeRecord;
2384 classRangeRecord = classRangeRecords + 6 * m;
2385 strawStart = ttUSHORT(classRangeRecord);
2386 strawEnd = ttUSHORT(classRangeRecord + 2);
2387 if (needle < strawStart)
2389 else if (needle > strawEnd)
2392 return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2395 classDefTable = classRangeRecords + 6 * classRangeCount;
2408 #define STBTT_GPOS_TODO_assert(x)
2410 #pragma warning( push )
2411 #pragma warning( disable : 4189)
2413 static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(
const stbtt_fontinfo *info,
int glyph1,
int glyph2)
2415 stbtt_uint16 lookupListOffset;
2416 stbtt_uint8 *lookupList;
2417 stbtt_uint16 lookupCount;
2421 if (!info->
gpos)
return 0;
2425 if (ttUSHORT(data+0) != 1)
return 0;
2426 if (ttUSHORT(data+2) != 0)
return 0;
2428 lookupListOffset = ttUSHORT(data+8);
2429 lookupList = data + lookupListOffset;
2430 lookupCount = ttUSHORT(lookupList);
2432 for (i=0; i<lookupCount; ++i) {
2433 stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2434 stbtt_uint8 *lookupTable = lookupList + lookupOffset;
2436 stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2437 stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2438 stbtt_uint8 *subTableOffsets = lookupTable + 6;
2439 switch(lookupType) {
2442 for (sti=0; sti<subTableCount; sti++) {
2443 stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2444 stbtt_uint8 *table = lookupTable + subtableOffset;
2445 stbtt_uint16 posFormat = ttUSHORT(table);
2446 stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2447 stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2448 if (coverageIndex == -1)
continue;
2450 switch (posFormat) {
2452 stbtt_int32 l, r, m;
2454 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2455 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2456 stbtt_int32 valueRecordPairSizeInBytes = 2;
2457 stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2458 stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2459 stbtt_uint8 *pairValueTable = table + pairPosOffset;
2460 stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2461 stbtt_uint8 *pairValueArray = pairValueTable + 2;
2463 STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2464 if (valueFormat1 != 4)
return 0;
2465 STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2466 if (valueFormat2 != 0)
return 0;
2468 STBTT_assert(coverageIndex < pairSetCount);
2476 stbtt_uint16 secondGlyph;
2477 stbtt_uint8 *pairValue;
2479 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2480 secondGlyph = ttUSHORT(pairValue);
2481 straw = secondGlyph;
2484 else if (needle > straw)
2487 stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2494 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2495 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2497 stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2498 stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2499 int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2500 int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2502 stbtt_uint16 class1Count = ttUSHORT(table + 12);
2503 stbtt_uint16 class2Count = ttUSHORT(table + 14);
2504 STBTT_assert(glyph1class < class1Count);
2505 STBTT_assert(glyph2class < class2Count);
2508 STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2509 if (valueFormat1 != 4)
return 0;
2510 STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2511 if (valueFormat2 != 0)
return 0;
2513 if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
2514 stbtt_uint8 *class1Records = table + 16;
2515 stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
2516 stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2540 #pragma warning( pop )
2547 xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
2550 xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
2569 if (ascent ) *ascent = ttSHORT(info->
data+info->
hhea + 4);
2570 if (descent) *descent = ttSHORT(info->
data+info->
hhea + 6);
2571 if (lineGap) *lineGap = ttSHORT(info->
data+info->
hhea + 8);
2576 int tab = stbtt__find_table(info->
data, info->
fontstart,
"OS/2");
2579 if (typoAscent ) *typoAscent = ttSHORT(info->
data+tab + 68);
2580 if (typoDescent) *typoDescent = ttSHORT(info->
data+tab + 70);
2581 if (typoLineGap) *typoLineGap = ttSHORT(info->
data+tab + 72);
2587 *x0 = ttSHORT(info->
data + info->
head + 36);
2588 *y0 = ttSHORT(info->
data + info->
head + 38);
2589 *x1 = ttSHORT(info->
data + info->
head + 40);
2590 *y1 = ttSHORT(info->
data + info->
head + 42);
2595 int fheight = ttSHORT(info->
data + info->
hhea + 4) - ttSHORT(info->
data + info->
hhea + 6);
2596 return (
float) height / fheight;
2601 int unitsPerEm = ttUSHORT(info->
data + info->
head + 18);
2602 return pixels / unitsPerEm;
2617 int x0=0,y0=0,x1,y1;
2626 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
2627 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
2628 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
2629 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
2640 stbtt_GetGlyphBitmapBoxSubpixel(font,
stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
2652 typedef struct stbtt__hheap_chunk
2654 struct stbtt__hheap_chunk *next;
2655 } stbtt__hheap_chunk;
2657 typedef struct stbtt__hheap
2659 struct stbtt__hheap_chunk *head;
2661 int num_remaining_in_head_chunk;
2664 static void *stbtt__hheap_alloc(stbtt__hheap *hh,
size_t size,
void *userdata)
2666 if (hh->first_free) {
2667 void *p = hh->first_free;
2668 hh->first_free = * (
void **) p;
2671 if (hh->num_remaining_in_head_chunk == 0) {
2672 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
2673 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(
sizeof(stbtt__hheap_chunk) + size * count, userdata);
2678 hh->num_remaining_in_head_chunk = count;
2680 --hh->num_remaining_in_head_chunk;
2681 return (
char *) (hh->head) +
sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
2685 static void stbtt__hheap_free(stbtt__hheap *hh,
void *p)
2687 *(
void **) p = hh->first_free;
2691 static void stbtt__hheap_cleanup(stbtt__hheap *hh,
void *userdata)
2693 stbtt__hheap_chunk *c = hh->head;
2695 stbtt__hheap_chunk *n = c->next;
2696 STBTT_free(c, userdata);
2701 typedef struct stbtt__edge {
2707 typedef struct stbtt__active_edge
2709 struct stbtt__active_edge *next;
2710 #if STBTT_RASTERIZER_VERSION==1
2714 #elif STBTT_RASTERIZER_VERSION==2
2720 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2722 } stbtt__active_edge;
2724 #if STBTT_RASTERIZER_VERSION == 1
2725 #define STBTT_FIXSHIFT 10
2726 #define STBTT_FIX (1 << STBTT_FIXSHIFT)
2727 #define STBTT_FIXMASK (STBTT_FIX-1)
2729 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e,
int off_x,
float start_point,
void *userdata)
2731 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh,
sizeof(*z), userdata);
2732 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2733 STBTT_assert(z != NULL);
2738 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
2740 z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
2742 z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0));
2743 z->x -= off_x * STBTT_FIX;
2747 z->direction = e->invert ? 1 : -1;
2750 #elif STBTT_RASTERIZER_VERSION == 2
2751 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e,
int off_x,
float start_point,
void *userdata)
2753 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh,
sizeof(*z), userdata);
2754 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
2755 STBTT_assert(z != NULL);
2759 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
2760 z->fx = e->x0 + dxdy * (start_point - e->y0);
2762 z->direction = e->invert ? 1.0f : -1.0f;
2769 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
2772 #if STBTT_RASTERIZER_VERSION == 1
2776 static void stbtt__fill_active_edges(
unsigned char *scanline,
int len, stbtt__active_edge *e,
int max_weight)
2784 x0 = e->x; w += e->direction;
2786 int x1 = e->x; w += e->direction;
2789 int i = x0 >> STBTT_FIXSHIFT;
2790 int j = x1 >> STBTT_FIXSHIFT;
2792 if (i < len && j >= 0) {
2795 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
2798 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
2803 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
2807 for (++i; i < j; ++i)
2808 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
2818 static void stbtt__rasterize_sorted_edges(
stbtt__bitmap *result, stbtt__edge *e,
int n,
int vsubsample,
int off_x,
int off_y,
void *userdata)
2820 stbtt__hheap hh = { 0, 0, 0 };
2821 stbtt__active_edge *active = NULL;
2823 int max_weight = (255 / vsubsample);
2825 unsigned char scanline_data[512], *scanline;
2827 if (result->
w > 512)
2828 scanline = (
unsigned char *) STBTT_malloc(result->
w, userdata);
2830 scanline = scanline_data;
2832 y = off_y * vsubsample;
2833 e[n].y0 = (off_y + result->
h) * (
float) vsubsample + 1;
2835 while (j < result->h) {
2836 STBTT_memset(scanline, 0, result->
w);
2837 for (s=0; s < vsubsample; ++s) {
2839 float scan_y = y + 0.5f;
2840 stbtt__active_edge **step = &active;
2845 stbtt__active_edge * z = *step;
2846 if (z->ey <= scan_y) {
2848 STBTT_assert(z->direction);
2850 stbtt__hheap_free(&hh, z);
2853 step = &((*step)->next);
2861 while (*step && (*step)->next) {
2862 if ((*step)->x > (*step)->next->x) {
2863 stbtt__active_edge *t = *step;
2864 stbtt__active_edge *q = t->next;
2871 step = &(*step)->next;
2873 if (!changed)
break;
2877 while (e->y0 <= scan_y) {
2878 if (e->y1 > scan_y) {
2879 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
2884 else if (z->x < active->x) {
2890 stbtt__active_edge *p = active;
2891 while (p->next && p->next->x < z->x)
2904 stbtt__fill_active_edges(scanline, result->
w, active, max_weight);
2908 STBTT_memcpy(result->
pixels + j * result->
stride, scanline, result->
w);
2912 stbtt__hheap_cleanup(&hh, userdata);
2914 if (scanline != scanline_data)
2915 STBTT_free(scanline, userdata);
2918 #elif STBTT_RASTERIZER_VERSION == 2
2922 static void stbtt__handle_clipped_edge(
float *scanline,
int x, stbtt__active_edge *e,
float x0,
float y0,
float x1,
float y1)
2924 if (y0 == y1)
return;
2925 STBTT_assert(y0 < y1);
2926 STBTT_assert(e->sy <= e->ey);
2927 if (y0 > e->ey)
return;
2928 if (y1 < e->sy)
return;
2930 x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
2934 x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
2939 STBTT_assert(x1 <= x+1);
2941 STBTT_assert(x1 >= x);
2943 STBTT_assert(x1 <= x);
2945 STBTT_assert(x1 >= x+1);
2947 STBTT_assert(x1 >= x && x1 <= x+1);
2949 if (x0 <= x && x1 <= x)
2950 scanline[x] += e->direction * (y1-y0);
2951 else if (x0 >= x+1 && x1 >= x+1)
2954 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
2955 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2);
2959 static void stbtt__fill_active_edges_new(
float *scanline,
float *scanline_fill,
int len, stbtt__active_edge *e,
float y_top)
2961 float y_bottom = y_top+1;
2967 STBTT_assert(e->ey >= y_top);
2973 stbtt__handle_clipped_edge(scanline,(
int) x0,e, x0,y_top, x0,y_bottom);
2974 stbtt__handle_clipped_edge(scanline_fill-1,(
int) x0+1,e, x0,y_top, x0,y_bottom);
2976 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
2983 float x_top, x_bottom;
2986 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
2991 if (e->sy > y_top) {
2992 x_top = x0 + dx * (e->sy - y_top);
2998 if (e->ey < y_bottom) {
2999 x_bottom = x0 + dx * (e->ey - y_top);
3006 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
3009 if ((
int) x_top == (
int) x_bottom) {
3012 int x = (
int) x_top;
3014 STBTT_assert(x >= 0 && x < len);
3015 scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
3016 scanline_fill[x] += e->direction * height;
3019 float y_crossing, step, sign, area;
3021 if (x_top > x_bottom) {
3024 sy0 = y_bottom - (sy0 - y_top);
3025 sy1 = y_bottom - (sy1 - y_top);
3026 t = sy0, sy0 = sy1, sy1 = t;
3027 t = x_bottom, x_bottom = x_top, x_top = t;
3030 t = x0, x0 = xb, xb = t;
3034 x2 = (
int) x_bottom;
3036 y_crossing = (x1+1 - x0) * dy + y_top;
3038 sign = e->direction;
3040 area = sign * (y_crossing-sy0);
3042 scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
3045 for (x = x1+1; x < x2; ++x) {
3046 scanline[x] += area + step/2;
3049 y_crossing += dy * (x2 - (x1+1));
3051 STBTT_assert(STBTT_fabs(area) <= 1.01f);
3053 scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
3055 scanline_fill[x2] += sign * (sy1-sy0);
3063 for (x=0; x < len; ++x) {
3079 float x1 = (float) (x);
3080 float x2 = (float) (x+1);
3082 float y3 = y_bottom;
3087 float y1 = (x - x0) / dx + y_top;
3088 float y2 = (x+1 - x0) / dx + y_top;
3090 if (x0 < x1 && x3 > x2) {
3091 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3092 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
3093 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3094 }
else if (x3 < x1 && x0 > x2) {
3095 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3096 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
3097 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3098 }
else if (x0 < x1 && x3 > x1) {
3099 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3100 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3101 }
else if (x3 < x1 && x0 > x1) {
3102 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
3103 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
3104 }
else if (x0 < x2 && x3 > x2) {
3105 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3106 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3107 }
else if (x3 < x2 && x0 > x2) {
3108 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
3109 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
3111 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
3121 static void stbtt__rasterize_sorted_edges(
stbtt__bitmap *result, stbtt__edge *e,
int n,
int vsubsample,
int off_x,
int off_y,
void *userdata)
3123 stbtt__hheap hh = { 0, 0, 0 };
3124 stbtt__active_edge *active = NULL;
3126 float scanline_data[129], *scanline, *scanline2;
3128 STBTT__NOTUSED(vsubsample);
3131 scanline = (
float *) STBTT_malloc((result->
w*2+1) *
sizeof(float), userdata);
3133 scanline = scanline_data;
3135 scanline2 = scanline + result->
w;
3138 e[n].y0 = (float) (off_y + result->
h) + 1;
3140 while (j < result->h) {
3142 float scan_y_top = y + 0.0f;
3143 float scan_y_bottom = y + 1.0f;
3144 stbtt__active_edge **step = &active;
3146 STBTT_memset(scanline , 0, result->
w*
sizeof(scanline[0]));
3147 STBTT_memset(scanline2, 0, (result->
w+1)*
sizeof(scanline[0]));
3152 stbtt__active_edge * z = *step;
3153 if (z->ey <= scan_y_top) {
3155 STBTT_assert(z->direction);
3157 stbtt__hheap_free(&hh, z);
3159 step = &((*step)->next);
3164 while (e->y0 <= scan_y_bottom) {
3165 if (e->y0 != e->y1) {
3166 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
3168 STBTT_assert(z->ey >= scan_y_top);
3179 stbtt__fill_active_edges_new(scanline, scanline2+1, result->
w, active, scan_y_top);
3183 for (i=0; i < result->
w; ++i) {
3186 sum += scanline2[i];
3187 k = scanline[i] + sum;
3188 k = (float) STBTT_fabs(k)*255 + 0.5f;
3190 if (m > 255) m = 255;
3197 stbtt__active_edge *z = *step;
3199 step = &((*step)->next);
3206 stbtt__hheap_cleanup(&hh, userdata);
3208 if (scanline != scanline_data)
3209 STBTT_free(scanline, userdata);
3212 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3215 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
3217 static void stbtt__sort_edges_ins_sort(stbtt__edge *p,
int n)
3220 for (i=1; i < n; ++i) {
3221 stbtt__edge t = p[i], *a = &t;
3224 stbtt__edge *b = &p[j-1];
3225 int c = STBTT__COMPARE(a,b);
3235 static void stbtt__sort_edges_quicksort(stbtt__edge *p,
int n)
3240 int c01,c12,c,m,i,j;
3244 c01 = STBTT__COMPARE(&p[0],&p[m]);
3245 c12 = STBTT__COMPARE(&p[m],&p[n-1]);
3250 c = STBTT__COMPARE(&p[0],&p[n-1]);
3253 z = (c == c12) ? 0 : n-1;
3271 if (!STBTT__COMPARE(&p[i], &p[0]))
break;
3274 if (!STBTT__COMPARE(&p[0], &p[j]))
break;
3287 stbtt__sort_edges_quicksort(p,j);
3291 stbtt__sort_edges_quicksort(p+i, n-i);
3297 static void stbtt__sort_edges(stbtt__edge *p,
int n)
3299 stbtt__sort_edges_quicksort(p, n);
3300 stbtt__sort_edges_ins_sort(p, n);
3308 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)
3310 float y_scale_inv = invert ? -scale_y : scale_y;
3313 #if STBTT_RASTERIZER_VERSION == 1
3314 int vsubsample = result->
h < 8 ? 15 : 5;
3315 #elif STBTT_RASTERIZER_VERSION == 2
3318 #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
3324 for (i=0; i < windings; ++i)
3327 e = (stbtt__edge *) STBTT_malloc(
sizeof(*e) * (n+1), userdata);
3332 for (i=0; i < windings; ++i) {
3333 stbtt__point *p = pts + m;
3336 for (k=0; k < wcount[i]; j=k++) {
3339 if (p[j].y == p[k].y)
3343 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
3347 e[n].x0 = p[a].x * scale_x + shift_x;
3348 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
3349 e[n].x1 = p[b].x * scale_x + shift_x;
3350 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
3357 stbtt__sort_edges(e, n);
3360 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
3362 STBTT_free(e, userdata);
3365 static void stbtt__add_point(stbtt__point *points,
int n,
float x,
float y)
3367 if (!points)
return;
3373 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)
3376 float mx = (x0 + 2*x1 + x2)/4;
3377 float my = (y0 + 2*y1 + y2)/4;
3379 float dx = (x0+x2)/2 - mx;
3380 float dy = (y0+y2)/2 - my;
3383 if (dx*dx+dy*dy > objspace_flatness_squared) {
3384 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
3385 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
3387 stbtt__add_point(points, *num_points,x2,y2);
3388 *num_points = *num_points+1;
3393 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)
3404 float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
3405 float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
3406 float flatness_squared = longlen*longlen-shortlen*shortlen;
3411 if (flatness_squared > objspace_flatness_squared) {
3412 float x01 = (x0+x1)/2;
3413 float y01 = (y0+y1)/2;
3414 float x12 = (x1+x2)/2;
3415 float y12 = (y1+y2)/2;
3416 float x23 = (x2+x3)/2;
3417 float y23 = (y2+y3)/2;
3419 float xa = (x01+x12)/2;
3420 float ya = (y01+y12)/2;
3421 float xb = (x12+x23)/2;
3422 float yb = (y12+y23)/2;
3424 float mx = (xa+xb)/2;
3425 float my = (ya+yb)/2;
3427 stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
3428 stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
3430 stbtt__add_point(points, *num_points,x3,y3);
3431 *num_points = *num_points+1;
3436 static stbtt__point *stbtt_FlattenCurves(
stbtt_vertex *vertices,
int num_verts,
float objspace_flatness,
int **contour_lengths,
int *num_contours,
void *userdata)
3438 stbtt__point *points=0;
3441 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
3442 int i,n=0,start=0, pass;
3445 for (i=0; i < num_verts; ++i)
3450 if (n == 0)
return 0;
3452 *contour_lengths = (
int *) STBTT_malloc(
sizeof(**contour_lengths) * n, userdata);
3454 if (*contour_lengths == 0) {
3460 for (pass=0; pass < 2; ++pass) {
3463 points = (stbtt__point *) STBTT_malloc(num_points *
sizeof(points[0]), userdata);
3464 if (points == NULL)
goto error;
3468 for (i=0; i < num_verts; ++i) {
3469 switch (vertices[i].type) {
3473 (*contour_lengths)[n] = num_points - start;
3477 x = vertices[i].
x, y = vertices[i].
y;
3478 stbtt__add_point(points, num_points++, x,y);
3481 x = vertices[i].
x, y = vertices[i].
y;
3482 stbtt__add_point(points, num_points++, x, y);
3485 stbtt__tesselate_curve(points, &num_points, x,y,
3486 vertices[i].cx, vertices[i].cy,
3487 vertices[i].x, vertices[i].y,
3488 objspace_flatness_squared, 0);
3489 x = vertices[i].
x, y = vertices[i].
y;
3492 stbtt__tesselate_cubic(points, &num_points, x,y,
3493 vertices[i].cx, vertices[i].cy,
3494 vertices[i].cx1, vertices[i].cy1,
3495 vertices[i].x, vertices[i].y,
3496 objspace_flatness_squared, 0);
3497 x = vertices[i].
x, y = vertices[i].
y;
3501 (*contour_lengths)[n] = num_points - start;
3506 STBTT_free(points, userdata);
3507 STBTT_free(*contour_lengths, userdata);
3508 *contour_lengths = 0;
3513 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)
3515 float scale = scale_x > scale_y ? scale_y : scale_x;
3516 int winding_count = 0;
3517 int *winding_lengths = NULL;
3518 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
3520 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
3521 STBTT_free(winding_lengths, userdata);
3522 STBTT_free(windings, userdata);
3528 STBTT_free(bitmap, userdata);
3533 int ix0,iy0,ix1,iy1;
3538 if (scale_x == 0) scale_x = scale_y;
3541 STBTT_free(vertices, info->
userdata);
3550 gbm.
w = (ix1 - ix0);
3551 gbm.
h = (iy1 - iy0);
3554 if (width ) *width = gbm.
w;
3555 if (height) *height = gbm.
h;
3556 if (xoff ) *xoff = ix0;
3557 if (yoff ) *yoff = iy0;
3559 if (gbm.
w && gbm.
h) {
3560 gbm.
pixels = (
unsigned char *) STBTT_malloc(gbm.
w * gbm.
h, info->
userdata);
3564 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->
userdata);
3567 STBTT_free(vertices, info->
userdata);
3590 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->
userdata);
3592 STBTT_free(vertices, info->
userdata);
3602 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y,
stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
3605 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)
3607 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));
3612 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y,
stbtt_FindGlyphIndex(info,codepoint));
3631 static int stbtt_BakeFontBitmap_internal(
unsigned char *data,
int offset,
3633 unsigned char *pixels,
int pw,
int ph,
3634 int first_char,
int num_chars,
3638 int x,y,bottom_y, i;
3643 STBTT_memset(pixels, 0, pw*ph);
3649 for (i=0; i < num_chars; ++i) {
3650 int advance, lsb, x0,y0,x1,y1,gw,gh;
3656 if (x + gw + 1 >= pw)
3657 y = bottom_y, x = 1;
3658 if (y + gh + 1 >= ph)
3660 STBTT_assert(x+gw < pw);
3661 STBTT_assert(y+gh < ph);
3663 chardata[i].
x0 = (stbtt_int16) x;
3664 chardata[i].
y0 = (stbtt_int16) y;
3665 chardata[i].
x1 = (stbtt_int16) (x + gw);
3666 chardata[i].
y1 = (stbtt_int16) (y + gh);
3667 chardata[i].
xadvance = scale * advance;
3668 chardata[i].
xoff = (float) x0;
3669 chardata[i].
yoff = (float) y0;
3671 if (y+gh+1 > bottom_y)
3679 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
3680 float ipw = 1.0f / pw, iph = 1.0f / ph;
3682 int round_x = STBTT_ifloor((*xpos + b->
xoff) + 0.5f);
3683 int round_y = STBTT_ifloor((*ypos + b->
yoff) + 0.5f);
3685 q->
x0 = round_x + d3d_bias;
3686 q->
y0 = round_y + d3d_bias;
3687 q->
x1 = round_x + b->
x1 - b->
x0 + d3d_bias;
3688 q->
y1 = round_y + b->
y1 - b->
y0 + d3d_bias;
3690 q->
s0 = b->
x0 * ipw;
3691 q->
t0 = b->
y0 * iph;
3692 q->
s1 = b->
x1 * ipw;
3693 q->
t1 = b->
y1 * iph;
3703 #ifndef STB_RECT_PACK_VERSION
3742 STBTT__NOTUSED(nodes);
3743 STBTT__NOTUSED(num_nodes);
3749 for (i=0; i < num_rects; ++i) {
3750 if (con->x + rects[i].
w > con->
width) {
3752 con->y = con->bottom_y;
3754 if (con->y + rects[i].
h > con->
height)
3756 rects[i].
x = con->x;
3757 rects[i].
y = con->y;
3759 con->x += rects[i].
w;
3760 if (con->y + rects[i].
h > con->bottom_y)
3761 con->bottom_y = con->y + rects[i].
h;
3763 for ( ; i < num_rects; ++i)
3764 rects[i].was_packed = 0;
3778 int num_nodes = pw - padding;
3781 if (context == NULL || nodes == NULL) {
3782 if (context != NULL) STBTT_free(context, alloc_context);
3783 if (nodes != NULL) STBTT_free(nodes , alloc_context);
3801 STBTT_memset(pixels, 0, pw*ph);
3814 STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
3815 STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
3816 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
3818 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
3822 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
3824 static void stbtt__h_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
3826 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
3827 int safe_w = w - kernel_width;
3829 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE);
3830 for (j=0; j < h; ++j) {
3833 STBTT_memset(buffer, 0, kernel_width);
3838 switch (kernel_width) {
3840 for (i=0; i <= safe_w; ++i) {
3841 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3842 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3843 pixels[i] = (
unsigned char) (total / 2);
3847 for (i=0; i <= safe_w; ++i) {
3848 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3849 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3850 pixels[i] = (
unsigned char) (total / 3);
3854 for (i=0; i <= safe_w; ++i) {
3855 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3856 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3857 pixels[i] = (
unsigned char) (total / 4);
3861 for (i=0; i <= safe_w; ++i) {
3862 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3863 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3864 pixels[i] = (
unsigned char) (total / 5);
3868 for (i=0; i <= safe_w; ++i) {
3869 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
3870 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
3871 pixels[i] = (
unsigned char) (total / kernel_width);
3876 for (; i < w; ++i) {
3877 STBTT_assert(pixels[i] == 0);
3878 total -= buffer[i & STBTT__OVER_MASK];
3879 pixels[i] = (
unsigned char) (total / kernel_width);
3882 pixels += stride_in_bytes;
3886 static void stbtt__v_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
3888 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
3889 int safe_h = h - kernel_width;
3891 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE);
3892 for (j=0; j < w; ++j) {
3895 STBTT_memset(buffer, 0, kernel_width);
3900 switch (kernel_width) {
3902 for (i=0; i <= safe_h; ++i) {
3903 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3904 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3905 pixels[i*stride_in_bytes] = (
unsigned char) (total / 2);
3909 for (i=0; i <= safe_h; ++i) {
3910 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3911 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3912 pixels[i*stride_in_bytes] = (
unsigned char) (total / 3);
3916 for (i=0; i <= safe_h; ++i) {
3917 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3918 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3919 pixels[i*stride_in_bytes] = (
unsigned char) (total / 4);
3923 for (i=0; i <= safe_h; ++i) {
3924 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3925 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3926 pixels[i*stride_in_bytes] = (
unsigned char) (total / 5);
3930 for (i=0; i <= safe_h; ++i) {
3931 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
3932 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
3933 pixels[i*stride_in_bytes] = (
unsigned char) (total / kernel_width);
3938 for (; i < h; ++i) {
3939 STBTT_assert(pixels[i*stride_in_bytes] == 0);
3940 total -= buffer[i & STBTT__OVER_MASK];
3941 pixels[i*stride_in_bytes] = (
unsigned char) (total / kernel_width);
3948 static float stbtt__oversample_shift(
int oversample)
3957 return (
float)-(oversample - 1) / (2.0f * (
float)oversample);
3966 for (i=0; i < num_ranges; ++i) {
3971 for (j=0; j < ranges[i].
num_chars; ++j) {
3989 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)
3993 out_w - (prefilter_x - 1),
3994 out_h - (prefilter_y - 1),
4002 if (prefilter_x > 1)
4003 stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
4005 if (prefilter_y > 1)
4006 stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
4008 *sub_x = stbtt__oversample_shift(prefilter_x);
4009 *sub_y = stbtt__oversample_shift(prefilter_y);
4015 int i,j,k, return_value = 1;
4022 for (i=0; i < num_ranges; ++i) {
4025 float recip_h,recip_v,sub_x,sub_y;
4032 for (j=0; j < ranges[i].
num_chars; ++j) {
4036 int advance, lsb, x0,y0,x1,y1;
4071 bc->
x0 = (stbtt_int16) r->
x;
4072 bc->
y0 = (stbtt_int16) r->
y;
4073 bc->
x1 = (stbtt_int16) (r->
x + r->
w);
4074 bc->
y1 = (stbtt_int16) (r->
y + r->
h);
4076 bc->
xoff = (float) x0 * recip_h + sub_x;
4077 bc->
yoff = (float) y0 * recip_v + sub_y;
4078 bc->
xoff2 = (x0 + r->
w) * recip_h + sub_x;
4079 bc->
yoff2 = (y0 + r->
h) * recip_v + sub_y;
4092 return return_value;
4103 int i,j,n, return_value = 1;
4108 for (i=0; i < num_ranges; ++i)
4110 ranges[i].chardata_for_range[j].x0 =
4111 ranges[i].chardata_for_range[j].y0 =
4112 ranges[i].chardata_for_range[j].x1 =
4113 ranges[i].chardata_for_range[j].y1 = 0;
4116 for (i=0; i < num_ranges; ++i)
4117 n += ranges[i].num_chars;
4133 return return_value;
4137 int first_unicode_codepoint_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range)
4150 float ipw = 1.0f / pw, iph = 1.0f / ph;
4153 if (align_to_integer) {
4154 float x = (float) STBTT_ifloor((*xpos + b->
xoff) + 0.5f);
4155 float y = (float) STBTT_ifloor((*ypos + b->
yoff) + 0.5f);
4167 q->
s0 = b->
x0 * ipw;
4168 q->
t0 = b->
y0 * iph;
4169 q->
s1 = b->
x1 * ipw;
4170 q->
t1 = b->
y1 * iph;
4180 #define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
4181 #define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
4183 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])
4185 float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
4186 float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
4187 float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
4188 float roperp = orig[1]*ray[0] - orig[0]*ray[1];
4190 float a = q0perp - 2*q1perp + q2perp;
4191 float b = q1perp - q0perp;
4192 float c = q0perp - roperp;
4194 float s0 = 0., s1 = 0.;
4198 float discr = b*b - a*c;
4200 float rcpna = -1 / a;
4201 float d = (float) STBTT_sqrt(discr);
4204 if (s0 >= 0.0 && s0 <= 1.0)
4206 if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
4207 if (num_s == 0) s0 = s1;
4215 if (s0 >= 0.0 && s0 <= 1.0)
4222 float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
4223 float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
4225 float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
4226 float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
4227 float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
4228 float rod = orig[0]*rayn_x + orig[1]*rayn_y;
4230 float q10d = q1d - q0d;
4231 float q20d = q2d - q0d;
4232 float q0rd = q0d - rod;
4234 hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
4235 hits[0][1] = a*s0+b;
4238 hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
4239 hits[1][1] = a*s1+b;
4247 static int equal(
float *a,
float *b)
4249 return (a[0] == b[0] && a[1] == b[1]);
4252 static int stbtt__compute_crossings_x(
float x,
float y,
int nverts,
stbtt_vertex *verts)
4255 float orig[2], ray[2] = { 1, 0 };
4263 y_frac = (float) STBTT_fmod(y, 1.0f);
4266 else if (y_frac > 0.99f)
4271 for (i=0; i < nverts; ++i) {
4273 int x0 = (
int) verts[i-1].x, y0 = (
int) verts[i-1].
y;
4274 int x1 = (
int) verts[i ].x, y1 = (
int) verts[i ].
y;
4275 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4276 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4278 winding += (y0 < y1) ? 1 : -1;
4282 int x0 = (
int) verts[i-1].x , y0 = (
int) verts[i-1].
y ;
4283 int x1 = (
int) verts[i ].cx, y1 = (
int) verts[i ].
cy;
4284 int x2 = (
int) verts[i ].x , y2 = (
int) verts[i ].
y ;
4285 int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
4286 int by = STBTT_max(y0,STBTT_max(y1,y2));
4287 if (y > ay && y < by && x > ax) {
4288 float q0[2],q1[2],q2[2];
4296 if (equal(q0,q1) || equal(q1,q2)) {
4297 x0 = (
int)verts[i-1].x;
4298 y0 = (
int)verts[i-1].y;
4299 x1 = (
int)verts[i ].x;
4300 y1 = (
int)verts[i ].y;
4301 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
4302 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
4304 winding += (y0 < y1) ? 1 : -1;
4307 int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
4310 winding += (hits[0][1] < 0 ? -1 : 1);
4313 winding += (hits[1][1] < 0 ? -1 : 1);
4321 static float stbtt__cuberoot(
float x )
4324 return -(float) STBTT_pow(-x,1.0f/3.0f);
4326 return (
float) STBTT_pow( x,1.0f/3.0f);
4330 static int stbtt__solve_cubic(
float a,
float b,
float c,
float* r)
4333 float p = b - a*a / 3;
4334 float q = a * (2*a*a - 9*b) / 27 + c;
4336 float d = q*q + 4*p3 / 27;
4338 float z = (float) STBTT_sqrt(d);
4339 float u = (-q + z) / 2;
4340 float v = (-q - z) / 2;
4341 u = stbtt__cuberoot(u);
4342 v = stbtt__cuberoot(v);
4346 float u = (float) STBTT_sqrt(-p/3);
4347 float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3;
4348 float m = (float) STBTT_cos(v);
4349 float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
4350 r[0] = s + u * 2 * m;
4351 r[1] = s - u * (m + n);
4352 r[2] = s - u * (m - n);
4361 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)
4363 float scale_x = scale, scale_y = scale;
4364 int ix0,iy0,ix1,iy1;
4366 unsigned char *data;
4369 if (scale_x == 0) scale_x = scale_y;
4371 if (scale_x == 0)
return NULL;
4378 if (ix0 == ix1 || iy0 == iy1)
4389 if (width ) *width = w;
4390 if (height) *height = h;
4391 if (xoff ) *xoff = ix0;
4392 if (yoff ) *yoff = iy0;
4402 data = (
unsigned char *) STBTT_malloc(w * h, info->
userdata);
4403 precompute = (
float *) STBTT_malloc(num_verts *
sizeof(
float), info->
userdata);
4405 for (i=0,j=num_verts-1; i < num_verts; j=i++) {
4407 float x0 = verts[i].
x*scale_x, y0 = verts[i].
y*scale_y;
4408 float x1 = verts[j].
x*scale_x, y1 = verts[j].
y*scale_y;
4409 float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
4410 precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
4412 float x2 = verts[j].
x *scale_x, y2 = verts[j].
y *scale_y;
4413 float x1 = verts[i].
cx*scale_x, y1 = verts[i].
cy*scale_y;
4414 float x0 = verts[i].
x *scale_x, y0 = verts[i].
y *scale_y;
4415 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4416 float len2 = bx*bx + by*by;
4418 precompute[i] = 1.0f / (bx*bx + by*by);
4420 precompute[i] = 0.0f;
4422 precompute[i] = 0.0f;
4425 for (y=iy0; y < iy1; ++y) {
4426 for (x=ix0; x < ix1; ++x) {
4428 float min_dist = 999999.0f;
4429 float sx = (float) x + 0.5f;
4430 float sy = (float) y + 0.5f;
4431 float x_gspace = (sx / scale_x);
4432 float y_gspace = (sy / scale_y);
4434 int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts);
4436 for (i=0; i < num_verts; ++i) {
4437 float x0 = verts[i].
x*scale_x, y0 = verts[i].
y*scale_y;
4440 float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4441 if (dist2 < min_dist*min_dist)
4442 min_dist = (float) STBTT_sqrt(dist2);
4445 float x1 = verts[i-1].
x*scale_x, y1 = verts[i-1].
y*scale_y;
4450 float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
4451 STBTT_assert(i != 0);
4452 if (dist < min_dist) {
4456 float dx = x1-x0, dy = y1-y0;
4457 float px = x0-sx, py = y0-sy;
4460 float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
4461 if (t >= 0.0f && t <= 1.0f)
4465 float x2 = verts[i-1].
x *scale_x, y2 = verts[i-1].
y *scale_y;
4466 float x1 = verts[i ].
cx*scale_x, y1 = verts[i ].
cy*scale_y;
4467 float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
4468 float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
4469 float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
4470 float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
4472 if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
4474 float ax = x1-x0, ay = y1-y0;
4475 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4476 float mx = x0 - sx, my = y0 - sy;
4477 float res[3],px,py,t,it;
4478 float a_inv = precompute[i];
4480 float a = 3*(ax*bx + ay*by);
4481 float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
4482 float c = mx*ax+my*ay;
4488 float discriminant = b*b - 4*a*c;
4489 if (discriminant < 0)
4492 float root = (float) STBTT_sqrt(discriminant);
4493 res[0] = (-b - root)/(2*a);
4494 res[1] = (-b + root)/(2*a);
4499 float b = 3*(ax*bx + ay*by) * a_inv;
4500 float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
4501 float d = (mx*ax+my*ay) * a_inv;
4502 num = stbtt__solve_cubic(b, c, d, res);
4504 if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
4505 t = res[0], it = 1.0f - t;
4506 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4507 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4508 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4509 if (dist2 < min_dist * min_dist)
4510 min_dist = (float) STBTT_sqrt(dist2);
4512 if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
4513 t = res[1], it = 1.0f - t;
4514 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4515 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4516 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4517 if (dist2 < min_dist * min_dist)
4518 min_dist = (float) STBTT_sqrt(dist2);
4520 if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
4521 t = res[2], it = 1.0f - t;
4522 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
4523 py = it*it*y0 + 2*t*it*y1 + t*t*y2;
4524 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
4525 if (dist2 < min_dist * min_dist)
4526 min_dist = (float) STBTT_sqrt(dist2);
4532 min_dist = -min_dist;
4533 val = onedge_value + pixel_dist_scale * min_dist;
4538 data[(y-iy0)*w+(x-ix0)] = (
unsigned char) val;
4541 STBTT_free(precompute, info->
userdata);
4547 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)
4549 return stbtt_GetGlyphSDF(info, scale,
stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
4554 STBTT_free(bitmap, userdata);
4563 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
4569 stbtt_uint16 ch = s2[0]*256 + s2[1];
4571 if (i >= len1)
return -1;
4572 if (s1[i++] != ch)
return -1;
4573 }
else if (ch < 0x800) {
4574 if (i+1 >= len1)
return -1;
4575 if (s1[i++] != 0xc0 + (ch >> 6))
return -1;
4576 if (s1[i++] != 0x80 + (ch & 0x3f))
return -1;
4577 }
else if (ch >= 0xd800 && ch < 0xdc00) {
4579 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
4580 if (i+3 >= len1)
return -1;
4581 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
4582 if (s1[i++] != 0xf0 + (c >> 18))
return -1;
4583 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f))
return -1;
4584 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f))
return -1;
4585 if (s1[i++] != 0x80 + ((c ) & 0x3f))
return -1;
4588 }
else if (ch >= 0xdc00 && ch < 0xe000) {
4591 if (i+2 >= len1)
return -1;
4592 if (s1[i++] != 0xe0 + (ch >> 12))
return -1;
4593 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f))
return -1;
4594 if (s1[i++] != 0x80 + ((ch ) & 0x3f))
return -1;
4602 static int stbtt_CompareUTF8toUTF16_bigendian_internal(
char *s1,
int len1,
char *s2,
int len2)
4604 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
4611 stbtt_int32 i,count,stringOffset;
4612 stbtt_uint8 *fc = font->
data;
4614 stbtt_uint32 nm = stbtt__find_table(fc, offset,
"name");
4615 if (!nm)
return NULL;
4617 count = ttUSHORT(fc+nm+2);
4618 stringOffset = nm + ttUSHORT(fc+nm+4);
4619 for (i=0; i < count; ++i) {
4620 stbtt_uint32 loc = nm + 6 + 12 * i;
4621 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
4622 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
4623 *length = ttUSHORT(fc+loc+8);
4624 return (
const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
4630 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
4633 stbtt_int32 count = ttUSHORT(fc+nm+2);
4634 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
4636 for (i=0; i < count; ++i) {
4637 stbtt_uint32 loc = nm + 6 + 12 * i;
4638 stbtt_int32
id = ttUSHORT(fc+loc+6);
4639 if (
id == target_id) {
4641 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
4644 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
4645 stbtt_int32 slen = ttUSHORT(fc+loc+8);
4646 stbtt_int32 off = ttUSHORT(fc+loc+10);
4649 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
4650 if (matchlen >= 0) {
4652 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) {
4653 slen = ttUSHORT(fc+loc+12+8);
4654 off = ttUSHORT(fc+loc+12+10);
4656 if (matchlen == nlen)
4658 }
else if (matchlen < nlen && name[matchlen] ==
' ') {
4660 if (stbtt_CompareUTF8toUTF16_bigendian_internal((
char*) (name+matchlen), nlen-matchlen, (
char*)(fc+stringOffset+off),slen))
4665 if (matchlen == nlen)
4677 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
4679 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((
char *) name);
4681 if (!stbtt__isfont(fc+offset))
return 0;
4685 hd = stbtt__find_table(fc, offset,
"head");
4686 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7))
return 0;
4689 nm = stbtt__find_table(fc, offset,
"name");
4694 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))
return 1;
4695 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1))
return 1;
4696 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
4698 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))
return 1;
4699 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2))
return 1;
4700 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
4706 static int stbtt_FindMatchingFont_internal(
unsigned char *font_collection,
char *name_utf8, stbtt_int32 flags)
4711 if (off < 0)
return off;
4712 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
4717 #if defined(__GNUC__) || defined(__clang__)
4718 #pragma GCC diagnostic push
4719 #pragma GCC diagnostic ignored "-Wcast-qual"
4723 float pixel_height,
unsigned char *pixels,
int pw,
int ph,
4726 return stbtt_BakeFontBitmap_internal((
unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
4731 return stbtt_GetFontOffsetForIndex_internal((
unsigned char *) data, index);
4736 return stbtt_GetNumberOfFonts_internal((
unsigned char *) data);
4741 return stbtt_InitFont_internal(info, (
unsigned char *) data, offset);
4746 return stbtt_FindMatchingFont_internal((
unsigned char *) fontdata, (
char *) name, flags);
4751 return stbtt_CompareUTF8toUTF16_bigendian_internal((
char *) s1, len1, (
char *) s2, len2);
4754 #if defined(__GNUC__) || defined(__clang__)
4755 #pragma GCC diagnostic pop
4758 #endif // STB_TRUETYPE_IMPLEMENTATION
int w
Definition: stb_truetype.h:893
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)
STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
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)
int kern
Definition: stb_truetype.h:707
Definition: stb_truetype.h:1044
int cursor
Definition: stb_truetype.h:511
float t0
Definition: stb_truetype.h:540
unsigned short x1
Definition: stb_truetype.h:524
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
Definition: stb_truetype.h:1014
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)
Definition: stb_truetype.h:522
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)
STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
stbtt_packedchar * chardata_for_range
Definition: stb_truetype.h:618
Definition: stb_truetype.h:1036
int index_map
Definition: stb_truetype.h:708
unsigned int v_oversample
Definition: stb_truetype.h:672
Definition: stb_truetype.h:1020
float x1
Definition: stb_truetype.h:541
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
Definition: stb_truetype.h:1056
Definition: stb_truetype.h:1027
float xoff
Definition: stb_truetype.h:525
int * array_of_unicode_codepoints
Definition: stb_truetype.h:616
int stride
Definition: stb_truetype.h:893
float x0
Definition: stb_truetype.h:540
STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices)
Definition: stb_truetype.h:1045
unsigned char type
Definition: stb_truetype.h:811
stbtt_vertex_type cy
Definition: stb_truetype.h:810
Definition: stb_truetype.h:1051
Definition: stb_truetype.h:1047
int height
Definition: stb_rect_pack.h:175
STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
Definition: stb_rect_pack.h:106
Definition: stb_truetype.h:1030
Definition: stb_rect_pack.h:166
Definition: stb_truetype.h:1042
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
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)
Definition: stb_truetype.h:538
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
Definition: stb_truetype.h:1036
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
Definition: stb_truetype.h:1029
voidpf void uLong size
Definition: ioapi.h:39
STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc)
STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
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)
stbtt__buf fdselect
Definition: stb_truetype.h:716
Definition: stb_truetype.h:800
Definition: stb_truetype.h:1043
STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
Definition: stb_truetype.h:1037
unsigned int h_oversample
Definition: stb_truetype.h:672
unsigned int GLuint
Definition: DtGlTextureBufferObject.h:18
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
Definition: stb_truetype.h:1045
Definition: stb_truetype.h:1035
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)
stbtt__buf cff
Definition: stb_truetype.h:711
unsigned short y1
Definition: stb_truetype.h:570
unsigned char * pixels
Definition: stb_truetype.h:894
STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
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)
stbtt__buf subrs
Definition: stb_truetype.h:714
Definition: stb_truetype.h:1023
void * nodes
Definition: stb_truetype.h:674
struct stbrp_context stbrp_context
Definition: stb_rect_pack.h:71
Definition: stb_truetype.h:1054
unsigned char v_oversample
Definition: stb_truetype.h:619
unsigned short stbrp_coord
Definition: stb_rect_pack.h:78
stbtt_vertex_type y
Definition: stb_truetype.h:810
#define stbtt_vertex_type
Definition: stb_truetype.h:807
int numGlyphs
Definition: stb_truetype.h:705
Definition: stb_truetype.h:1053
Definition: stb_truetype.h:612
stbrp_coord y
Definition: stb_rect_pack.h:115
Definition: stb_truetype.h:1051
Definition: stb_truetype.h:1046
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)
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)
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
Definition: stb_truetype.h:1021
STBTT_DEF const char * stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
stbtt__buf charstrings
Definition: stb_truetype.h:712
Definition: stb_truetype.h:1054
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)
Definition: stb_truetype.h:1055
int hmtx
Definition: stb_truetype.h:707
int was_packed
Definition: stb_rect_pack.h:116
Definition: stb_truetype.h:1044
Definition: stb_truetype.h:1047
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices)
STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
float xadvance
Definition: stb_truetype.h:525
stbtt__buf gsubrs
Definition: stb_truetype.h:713
int height
Definition: stb_truetype.h:669
int head
Definition: stb_truetype.h:707
STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
int hhea
Definition: stb_truetype.h:707
int glyf
Definition: stb_truetype.h:707
Definition: stb_truetype.h:1028
Definition: stb_truetype.h:1057
stbrp_coord x
Definition: stb_rect_pack.h:115
stbtt_vertex_type x
Definition: stb_truetype.h:810
float yoff2
Definition: stb_truetype.h:572
Definition: stb_truetype.h:1034
unsigned short x1
Definition: stb_truetype.h:570
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)
Definition: stb_truetype.h:665
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
float s0
Definition: stb_truetype.h:540
int fontstart
Definition: stb_truetype.h:703
Definition: stb_truetype.h:1055
float yoff
Definition: stb_truetype.h:571
stbrp_coord w
Definition: stb_rect_pack.h:112
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)
void * pack_info
Definition: stb_truetype.h:667
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)
struct stbrp_node stbrp_node
Definition: stb_rect_pack.h:72
Definition: stb_truetype.h:1035
Definition: stb_truetype.h:799
unsigned short y0
Definition: stb_truetype.h:570
Definition: stb_rect_pack.h:172
float xoff
Definition: stb_truetype.h:571
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)
Definition: asyncJobServer.h:39
unsigned char * data
Definition: stb_truetype.h:702
unsigned char h_oversample
Definition: stb_truetype.h:619
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)
Definition: stb_truetype.h:568
Definition: stb_truetype.h:1019
void * user_allocator_context
Definition: stb_truetype.h:666
#define STBTT_DEF
Definition: stb_truetype.h:500
Definition: stb_truetype.h:1015
Definition: stb_truetype.h:508
Definition: stb_truetype.h:1043
stbtt_vertex_type cx
Definition: stb_truetype.h:810
Definition: stb_truetype.h:1034
float s1
Definition: stb_truetype.h:541
Definition: stb_truetype.h:1013
stbtt__buf fontdicts
Definition: stb_truetype.h:715
int width
Definition: stb_rect_pack.h:174
float font_size
Definition: stb_truetype.h:614
unsigned short x0
Definition: stb_truetype.h:524
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)
Definition: stb_truetype.h:1012
Definition: stb_truetype.h:1037
int size
Definition: stb_truetype.h:512
Definition: stb_truetype.h:1053
STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
DT_DLL_VRVCORE double length(const makVrv::DtCoordinateSystem &, const std::vector< DtVector > &vertices)
Returns the total distance of a segmented line defined by the provided vector of vertices. Coordinates are in local database coordinates. The coordinate system is used to convert between the local database coordinates and geocentric. All distance is in 2D – the Z value is ignored.
STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
unsigned char * data
Definition: stb_truetype.h:510
Definition: stb_truetype.h:699
STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
stbrp_coord h
Definition: stb_rect_pack.h:112
int first_unicode_codepoint_in_range
Definition: stb_truetype.h:615
float y0
Definition: stb_truetype.h:540
STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
Definition: stb_truetype.h:1042
int h
Definition: stb_truetype.h:893
STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
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)
unsigned char * pixels
Definition: stb_truetype.h:673
unsigned short y0
Definition: stb_truetype.h:524
STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
int indexToLocFormat
Definition: stb_truetype.h:709
float yoff
Definition: stb_truetype.h:525
Definition: stb_truetype.h:798
STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, float pixel_height, unsigned char *pixels, int pw, int ph, int first_char, int num_chars, stbtt_bakedchar *chardata)
int id
Definition: stb_rect_pack.h:109
Definition: stb_truetype.h:1046
float xadvance
Definition: stb_truetype.h:571
STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels)
Definition: stb_truetype.h:1056
unsigned short y1
Definition: stb_truetype.h:524
float xoff2
Definition: stb_truetype.h:572
Definition: stb_truetype.h:1057
voidpf uLong offset
Definition: ioapi.h:42
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)
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
int stride_in_bytes
Definition: stb_truetype.h:670
Definition: stb_truetype.h:808
int gpos
Definition: stb_truetype.h:707
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)
int padding
Definition: stb_truetype.h:671
int num_chars
Definition: stb_truetype.h:617
float y1
Definition: stb_truetype.h:541
void * userdata
Definition: stb_truetype.h:701
Definition: stb_truetype.h:1052
Definition: stb_truetype.h:801
float t1
Definition: stb_truetype.h:541
int loca
Definition: stb_truetype.h:707
STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
Definition: stb_truetype.h:891
unsigned short x0
Definition: stb_truetype.h:570
STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
Definition: stb_truetype.h:1052
int width
Definition: stb_truetype.h:668
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
Definition: stb_truetype.h:1022