241 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation 244 unsigned char ttf_buffer[1<<20];
245 unsigned char temp_bitmap[512*512];
250 void my_stbtt_initfont(
void)
252 fread(ttf_buffer, 1, 1<<20, fopen(
"c:/windows/fonts/times.ttf",
"rb"));
262 void my_stbtt_print(
float x,
float y,
char *text)
269 if (*text >= 32 && *text < 128) {
290 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation 293 char ttf_buffer[1<<25];
295 int main(
int argc,
char **argv)
299 int w,
h,
i,
j,
c = (argc > 1 ? atoi(argv[1]) :
'a'),
s = (argc > 2 ? atoi(argv[2]) : 20);
301 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] :
"c:/windows/fonts/arialbd.ttf",
"rb"));
306 for (j=0; j <
h; ++
j) {
307 for (i=0; i <
w; ++
i)
308 putchar(
" .:ioVM@"[bitmap[j*w+i]>>5]);
334 unsigned char screen[20][79];
341 char *text =
"Heljo World!";
343 fread(buffer, 1, 1000000, fopen(
"c:/windows/fonts/arialbd.ttf",
"rb"));
348 baseline = (int) (ascent*scale);
352 float x_shift = xpos - (float) floor(xpos);
360 xpos += (advance *
scale);
366 for (j=0; j < 20; ++
j) {
367 for (i=0; i < 78; ++
i)
368 putchar(
" .:ioVM@"[screen[j][i]>>5]);
385 #ifdef STB_TRUETYPE_IMPLEMENTATION 388 typedef unsigned char stbtt_uint8;
389 typedef signed char stbtt_int8;
390 typedef unsigned short stbtt_uint16;
391 typedef signed short stbtt_int16;
392 typedef unsigned int stbtt_uint32;
393 typedef signed int stbtt_int32;
396 typedef char stbtt__check_size32[
sizeof(stbtt_int32)==4 ? 1 : -1];
397 typedef char stbtt__check_size16[
sizeof(stbtt_int16)==2 ? 1 : -1];
402 #define STBTT_ifloor(x) ((int) floor(x)) 403 #define STBTT_iceil(x) ((int) ceil(x)) 408 #define STBTT_sqrt(x) sqrt(x) 413 #define STBTT_fabs(x) fabs(x) 419 #define STBTT_malloc(x,u) ((void)(u),malloc(x)) 420 #define STBTT_free(x,u) ((void)(u),free(x)) 425 #define STBTT_assert(x) assert(x) 430 #define STBTT_strlen(x) strlen(x) 435 #define STBTT_memcpy memcpy 436 #define STBTT_memset memset 447 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__ 448 #define __STB_INCLUDE_STB_TRUETYPE_H__ 451 #define STBTT_DEF static 453 #define STBTT_DEF extern 475 unsigned char *
pixels,
int pw,
int ph,
476 int first_char,
int num_chars,
491 float *xpos,
float *
ypos,
493 int opengl_fillrule);
522 #ifndef STB_RECT_PACK_VERSION 540 #define STBTT_POINT_SIZE(x) (-(x)) 543 int first_unicode_char_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range);
591 float *xpos,
float *
ypos,
593 int align_to_integer);
647 int loca,head,glyf,hhea,hmtx,kern;
723 #ifndef STBTT_vmove // you can predefine these to use different values (but why?) 731 #ifndef stbtt_vertex // you can predefine this to use different values 733 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file 820 float flatness_in_pixels,
823 float scale_x,
float scale_y,
824 float shift_x,
float shift_y,
825 int x_off,
int y_off,
856 #define STBTT_MACSTYLE_DONTCARE 0 857 #define STBTT_MACSTYLE_BOLD 1 858 #define STBTT_MACSTYLE_ITALIC 2 859 #define STBTT_MACSTYLE_UNDERSCORE 4 860 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 927 #endif // __STB_INCLUDE_STB_TRUETYPE_H__ 936 #ifdef STB_TRUETYPE_IMPLEMENTATION 938 #ifndef STBTT_MAX_OVERSAMPLE 939 #define STBTT_MAX_OVERSAMPLE 8 942 #if STBTT_MAX_OVERSAMPLE > 255 943 #error "STBTT_MAX_OVERSAMPLE cannot be > 255" 946 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
948 #ifndef STBTT_RASTERIZER_VERSION 949 #define STBTT_RASTERIZER_VERSION 2 960 #define ttBYTE(p) (* (stbtt_uint8 *) (p)) 961 #define ttCHAR(p) (* (stbtt_int8 *) (p)) 962 #define ttFixed(p) ttLONG(p) 964 #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) 966 #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) 967 #define ttSHORT(p) (* (stbtt_int16 *) (p)) 968 #define ttULONG(p) (* (stbtt_uint32 *) (p)) 969 #define ttLONG(p) (* (stbtt_int32 *) (p)) 973 static stbtt_uint16 ttUSHORT(
const stbtt_uint8 *
p) {
return p[0]*256 + p[1]; }
974 static stbtt_int16 ttSHORT(
const stbtt_uint8 *
p) {
return p[0]*256 + p[1]; }
975 static stbtt_uint32 ttULONG(
const stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
976 static stbtt_int32 ttLONG(
const stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
980 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) 981 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) 983 static int stbtt__isfont(
const stbtt_uint8 *font)
986 if (stbtt_tag4(font,
'1',0,0,0))
return 1;
987 if (stbtt_tag(font,
"typ1"))
return 1;
988 if (stbtt_tag(font,
"OTTO"))
return 1;
989 if (stbtt_tag4(font, 0,1,0,0))
return 1;
994 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *
data, stbtt_uint32 fontstart,
const char *
tag)
996 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
997 stbtt_uint32 tabledir = fontstart + 12;
999 for (i=0; i < num_tables; ++
i) {
1000 stbtt_uint32 loc = tabledir + 16*
i;
1001 if (stbtt_tag(data+loc+0, tag))
1002 return ttULONG(data+loc+8);
1010 if (stbtt__isfont(font_collection))
1011 return index == 0 ? 0 : -1;
1014 if (stbtt_tag(font_collection,
"ttcf")) {
1016 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
1017 stbtt_int32
n = ttLONG(font_collection+8);
1020 return ttULONG(font_collection+12+index*4);
1028 stbtt_uint8 *data = (stbtt_uint8 *) data2;
1029 stbtt_uint32 cmap,
t;
1030 stbtt_int32
i,numTables;
1035 cmap = stbtt__find_table(data, fontstart,
"cmap");
1036 info->
loca = stbtt__find_table(data, fontstart,
"loca");
1037 info->
head = stbtt__find_table(data, fontstart,
"head");
1038 info->
glyf = stbtt__find_table(data, fontstart,
"glyf");
1039 info->
hhea = stbtt__find_table(data, fontstart,
"hhea");
1040 info->
hmtx = stbtt__find_table(data, fontstart,
"hmtx");
1041 info->
kern = stbtt__find_table(data, fontstart,
"kern");
1045 t = stbtt__find_table(data, fontstart,
"maxp");
1054 numTables = ttUSHORT(data + cmap + 2);
1056 for (i=0; i < numTables; ++
i) {
1057 stbtt_uint32 encoding_record = cmap + 4 + 8 *
i;
1059 switch(ttUSHORT(data+encoding_record)) {
1061 switch (ttUSHORT(data+encoding_record+2)) {
1065 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1072 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1085 stbtt_uint8 *data = info->
data;
1086 stbtt_uint32 index_map = info->
index_map;
1088 stbtt_uint16
format = ttUSHORT(data + index_map + 0);
1090 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1091 if (unicode_codepoint < bytes-6)
1092 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1094 }
else if (format == 6) {
1095 stbtt_uint32
first = ttUSHORT(data + index_map + 6);
1096 stbtt_uint32
count = ttUSHORT(data + index_map + 8);
1097 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1098 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1100 }
else if (format == 2) {
1103 }
else if (format == 4) {
1104 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1105 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1106 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1107 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1110 stbtt_uint32 endCount = index_map + 14;
1111 stbtt_uint32 search = endCount;
1113 if (unicode_codepoint > 0xffff)
1118 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1119 search += rangeShift*2;
1123 while (entrySelector) {
1126 end = ttUSHORT(data + search + searchRange*2);
1127 if (unicode_codepoint > end)
1128 search += searchRange*2;
1135 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
1137 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1138 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1139 if (unicode_codepoint < start)
1142 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1144 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1146 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1148 }
else if (format == 12 || format == 13) {
1149 stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1151 low = 0; high = (stbtt_int32)ngroups;
1153 while (low < high) {
1154 stbtt_int32 mid = low + ((high-
low) >> 1);
1155 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1156 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1157 if ((stbtt_uint32) unicode_codepoint < start_char)
1159 else if ((stbtt_uint32) unicode_codepoint > end_char)
1162 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1164 return start_glyph + unicode_codepoint-start_char;
1181 static void stbtt_setvertex(
stbtt_vertex *
v, stbtt_uint8
type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1184 v->
x = (stbtt_int16) x;
1185 v->
y = (stbtt_int16) y;
1186 v->
cx = (stbtt_int16) cx;
1187 v->
cy = (stbtt_int16) cy;
1190 static int stbtt__GetGlyfOffset(
const stbtt_fontinfo *info,
int glyph_index)
1194 if (glyph_index >= info->
numGlyphs)
return -1;
1198 g1 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2) * 2;
1199 g2 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2 + 2) * 2;
1201 g1 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4);
1202 g2 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4 + 4);
1205 return g1==g2 ? -1 : g1;
1210 int g = stbtt__GetGlyfOffset(info, glyph_index);
1211 if (g < 0)
return 0;
1213 if (x0) *x0 = ttSHORT(info->
data + g + 2);
1214 if (y0) *y0 = ttSHORT(info->
data + g + 4);
1215 if (x1) *x1 = ttSHORT(info->
data + g + 6);
1216 if (y1) *y1 = ttSHORT(info->
data + g + 8);
1227 stbtt_int16 numberOfContours;
1228 int g = stbtt__GetGlyfOffset(info, glyph_index);
1229 if (g < 0)
return 1;
1230 numberOfContours = ttSHORT(info->
data + g);
1231 return numberOfContours == 0;
1234 static int stbtt__close_shape(
stbtt_vertex *vertices,
int num_vertices,
int was_off,
int start_off,
1235 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1239 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1240 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, sx,sy,scx,scy);
1243 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve,sx,sy,cx,cy);
1245 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline,sx,sy,0,0);
1247 return num_vertices;
1252 stbtt_int16 numberOfContours;
1253 stbtt_uint8 *endPtsOfContours;
1254 stbtt_uint8 *data = info->
data;
1257 int g = stbtt__GetGlyfOffset(info, glyph_index);
1261 if (g < 0)
return 0;
1263 numberOfContours = ttSHORT(data + g);
1265 if (numberOfContours > 0) {
1266 stbtt_uint8
flags=0,flagcount;
1267 stbtt_int32 ins,
i,j=0,
m,
n, next_move, was_off=0, off, start_off=0;
1268 stbtt_int32
x,
y,cx,cy,sx,sy, scx,scy;
1270 endPtsOfContours = (data + g + 10);
1271 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1272 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1274 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1276 m = n + 2*numberOfContours;
1292 for (i=0; i <
n; ++
i) {
1293 if (flagcount == 0) {
1296 flagcount = *points++;
1304 for (i=0; i <
n; ++
i) {
1305 flags = vertices[off+
i].
type;
1307 stbtt_int16 dx = *points++;
1308 x += (flags & 16) ? dx : -dx;
1310 if (!(flags & 16)) {
1311 x = x + (stbtt_int16) (points[0]*256 + points[1]);
1315 vertices[off+
i].
x = (stbtt_int16) x;
1320 for (i=0; i <
n; ++
i) {
1321 flags = vertices[off+
i].
type;
1323 stbtt_int16 dy = *points++;
1324 y += (flags & 32) ? dy : -dy;
1326 if (!(flags & 32)) {
1327 y = y + (stbtt_int16) (points[0]*256 + points[1]);
1331 vertices[off+
i].
y = (stbtt_int16) y;
1336 sx = sy = cx = cy = scx = scy = 0;
1337 for (i=0; i <
n; ++
i) {
1338 flags = vertices[off+
i].
type;
1339 x = (stbtt_int16) vertices[off+i].x;
1340 y = (stbtt_int16) vertices[off+i].y;
1342 if (next_move == i) {
1344 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1347 start_off = !(flags & 1);
1353 if (!(vertices[off+i+1].type & 1)) {
1355 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1356 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1359 sx = (stbtt_int32) vertices[off+i+1].x;
1360 sy = (stbtt_int32) vertices[off+i+1].y;
1367 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vmove,sx,sy,0,0);
1369 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1374 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1380 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, x,y, cx, cy);
1382 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline, x,y,0,0);
1387 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1388 }
else if (numberOfContours == -1) {
1391 stbtt_uint8 *comp = data + g + 10;
1395 stbtt_uint16
flags, gidx;
1396 int comp_num_verts = 0,
i;
1398 float mtx[6] = {1,0,0,1,0,0},
m,
n;
1400 flags = ttSHORT(comp); comp+=2;
1401 gidx = ttSHORT(comp); comp+=2;
1405 mtx[4] = ttSHORT(comp); comp+=2;
1406 mtx[5] = ttSHORT(comp); comp+=2;
1408 mtx[4] = ttCHAR(comp); comp+=1;
1409 mtx[5] = ttCHAR(comp); comp+=1;
1416 if (flags & (1<<3)) {
1417 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1418 mtx[1] = mtx[2] = 0;
1419 }
else if (flags & (1<<6)) {
1420 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1421 mtx[1] = mtx[2] = 0;
1422 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1423 }
else if (flags & (1<<7)) {
1424 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1425 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1426 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1427 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1431 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1432 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1436 if (comp_num_verts > 0) {
1438 for (i = 0; i < comp_num_verts; ++
i) {
1455 if (num_vertices > 0) STBTT_memcpy(
tmp, vertices, num_vertices*
sizeof(
stbtt_vertex));
1456 STBTT_memcpy(
tmp+num_vertices, comp_verts, comp_num_verts*
sizeof(
stbtt_vertex));
1460 num_vertices += comp_num_verts;
1463 more = flags & (1<<5);
1465 }
else if (numberOfContours < 0) {
1473 return num_vertices;
1478 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->
data+info->
hhea + 34);
1479 if (glyph_index < numOfLongHorMetrics) {
1480 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*glyph_index);
1481 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*glyph_index + 2);
1483 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*(numOfLongHorMetrics-1));
1484 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
1490 stbtt_uint8 *data = info->
data + info->
kern;
1491 stbtt_uint32 needle, straw;
1497 if (ttUSHORT(data+2) < 1)
1499 if (ttUSHORT(data+8) != 1)
1503 r = ttUSHORT(data+10) - 1;
1504 needle = glyph1 << 16 | glyph2;
1507 straw = ttULONG(data+18+(m*6));
1510 else if (needle > straw)
1513 return ttSHORT(data+22+(m*6));
1532 if (ascent ) *ascent = ttSHORT(info->
data+info->
hhea + 4);
1533 if (descent) *descent = ttSHORT(info->
data+info->
hhea + 6);
1534 if (lineGap) *lineGap = ttSHORT(info->
data+info->
hhea + 8);
1539 *x0 = ttSHORT(info->
data + info->
head + 36);
1540 *y0 = ttSHORT(info->
data + info->
head + 38);
1541 *x1 = ttSHORT(info->
data + info->
head + 40);
1542 *y1 = ttSHORT(info->
data + info->
head + 42);
1547 int fheight = ttSHORT(info->
data + info->
hhea + 4) - ttSHORT(info->
data + info->
hhea + 6);
1548 return (
float) height / fheight;
1553 int unitsPerEm = ttUSHORT(info->
data + info->
head + 18);
1554 return pixels / unitsPerEm;
1569 int x0=0,y0=0,
x1,
y1;
1578 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
1579 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
1580 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
1581 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
1592 stbtt_GetGlyphBitmapBoxSubpixel(font,
stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
1604 typedef struct stbtt__hheap_chunk
1606 struct stbtt__hheap_chunk *
next;
1607 } stbtt__hheap_chunk;
1609 typedef struct stbtt__hheap
1611 struct stbtt__hheap_chunk *head;
1613 int num_remaining_in_head_chunk;
1616 static void *stbtt__hheap_alloc(stbtt__hheap *hh,
size_t size,
void *userdata)
1618 if (hh->first_free) {
1619 void *p = hh->first_free;
1620 hh->first_free = * (
void **) p;
1623 if (hh->num_remaining_in_head_chunk == 0) {
1624 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
1625 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *)
STBTT_malloc(
sizeof(stbtt__hheap_chunk) + size *
count, userdata);
1630 hh->num_remaining_in_head_chunk =
count;
1632 --hh->num_remaining_in_head_chunk;
1633 return (
char *) (hh->head) + size * hh->num_remaining_in_head_chunk;
1637 static void stbtt__hheap_free(stbtt__hheap *hh,
void *p)
1639 *(
void **) p = hh->first_free;
1643 static void stbtt__hheap_cleanup(stbtt__hheap *hh,
void *userdata)
1645 stbtt__hheap_chunk *c = hh->head;
1647 stbtt__hheap_chunk *
n = c->next;
1653 typedef struct stbtt__edge {
1659 typedef struct stbtt__active_edge
1661 struct stbtt__active_edge *
next;
1662 #if STBTT_RASTERIZER_VERSION==1 1666 #elif STBTT_RASTERIZER_VERSION==2 1672 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 1674 } stbtt__active_edge;
1676 #if STBTT_RASTERIZER_VERSION == 1 1677 #define STBTT_FIXSHIFT 10 1678 #define STBTT_FIX (1 << STBTT_FIXSHIFT) 1679 #define STBTT_FIXMASK (STBTT_FIX-1) 1681 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *
e,
int off_x,
float start_point,
void *userdata)
1683 stbtt__active_edge *
z = (stbtt__active_edge *) stbtt__hheap_alloc(hh,
sizeof(*z), userdata);
1684 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
1690 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
1692 z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
1694 z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0));
1695 z->x -= off_x * STBTT_FIX;
1699 z->direction = e->invert ? 1 : -1;
1702 #elif STBTT_RASTERIZER_VERSION == 2 1703 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e,
int off_x,
float start_point,
void *userdata)
1705 stbtt__active_edge *
z = (stbtt__active_edge *) stbtt__hheap_alloc(hh,
sizeof(*z), userdata);
1706 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
1711 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0
f;
1712 z->fx = e->x0 + dxdy * (start_point - e->y0);
1714 z->direction = e->invert ? 1.0f : -1.0f;
1721 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 1724 #if STBTT_RASTERIZER_VERSION == 1 1728 static void stbtt__fill_active_edges(
unsigned char *scanline,
int len, stbtt__active_edge *e,
int max_weight)
1736 x0 = e->x; w += e->direction;
1738 int x1 = e->x; w += e->direction;
1741 int i = x0 >> STBTT_FIXSHIFT;
1742 int j = x1 >> STBTT_FIXSHIFT;
1744 if (i < len && j >= 0) {
1747 scanline[
i] = scanline[
i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
1750 scanline[
i] = scanline[
i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
1755 scanline[
j] = scanline[
j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
1759 for (++i; i <
j; ++
i)
1760 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
1770 static void stbtt__rasterize_sorted_edges(
stbtt__bitmap *
result, stbtt__edge *e,
int n,
int vsubsample,
int off_x,
int off_y,
void *userdata)
1772 stbtt__hheap hh = { 0, 0, 0 };
1773 stbtt__active_edge *active =
NULL;
1775 int max_weight = (255 / vsubsample);
1777 unsigned char scanline_data[512], *scanline;
1779 if (result->
w > 512)
1780 scanline = (
unsigned char *)
STBTT_malloc(result->
w, userdata);
1782 scanline = scanline_data;
1784 y = off_y * vsubsample;
1785 e[
n].y0 = (off_y + result->
h) * (
float) vsubsample + 1;
1788 STBTT_memset(scanline, 0, result->
w);
1789 for (s=0; s < vsubsample; ++
s) {
1791 float scan_y = y + 0.5f;
1792 stbtt__active_edge **step = &active;
1797 stbtt__active_edge *
z = *step;
1798 if (z->ey <= scan_y) {
1802 stbtt__hheap_free(&hh, z);
1805 step = &((*step)->next);
1813 while (*step && (*step)->next) {
1814 if ((*step)->x > (*step)->next->x) {
1815 stbtt__active_edge *
t = *step;
1816 stbtt__active_edge *
q = t->next;
1823 step = &(*step)->next;
1825 if (!changed)
break;
1829 while (e->y0 <= scan_y) {
1830 if (e->y1 > scan_y) {
1831 stbtt__active_edge *
z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
1836 else if (z->x < active->x) {
1842 stbtt__active_edge *p = active;
1843 while (p->next && p->next->x < z->x)
1856 stbtt__fill_active_edges(scanline, result->
w, active, max_weight);
1860 STBTT_memcpy(result->
pixels + j * result->
stride, scanline, result->
w);
1864 stbtt__hheap_cleanup(&hh, userdata);
1866 if (scanline != scanline_data)
1870 #elif STBTT_RASTERIZER_VERSION == 2 1874 static void stbtt__handle_clipped_edge(
float *scanline,
int x, stbtt__active_edge *e,
float x0,
float y0,
float x1,
float y1)
1876 if (y0 == y1)
return;
1879 if (y0 > e->ey)
return;
1882 x0 += (x1-
x0) * (e->sy - y0) / (y1-
y0);
1886 x1 += (x1-
x0) * (e->ey - y1) / (y1-
y0);
1901 if (x0 <= x && x1 <= x)
1902 scanline[
x] += e->direction * (y1-
y0);
1903 else if (x0 >= x+1 && x1 >= x+1)
1907 scanline[
x] += e->direction * (y1-
y0) * (1-((x0-x)+(x1-x))/2);
1911 static void stbtt__fill_active_edges_new(
float *scanline,
float *scanline_fill,
int len, stbtt__active_edge *e,
float y_top)
1913 float y_bottom = y_top+1;
1925 stbtt__handle_clipped_edge(scanline,(
int) x0,e, x0,y_top, x0,y_bottom);
1926 stbtt__handle_clipped_edge(scanline_fill-1,(
int) x0+1,e, x0,y_top, x0,y_bottom);
1928 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
1935 float x_top, x_bottom;
1943 if (e->sy > y_top) {
1944 x_top = x0 + dx * (e->sy - y_top);
1950 if (e->ey < y_bottom) {
1951 x_bottom = x0 + dx * (e->ey - y_top);
1958 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
1961 if ((
int) x_top == (int) x_bottom) {
1964 int x = (int) x_top;
1967 scanline[
x] += e->direction * (1-((x_top -
x) + (x_bottom-x))/2) *
height;
1968 scanline_fill[
x] += e->direction *
height;
1971 float y_crossing, step, sign, area;
1973 if (x_top > x_bottom) {
1976 sy0 = y_bottom - (sy0 - y_top);
1977 sy1 = y_bottom - (sy1 - y_top);
1978 t = sy0, sy0 = sy1, sy1 =
t;
1979 t = x_bottom, x_bottom = x_top, x_top =
t;
1982 t =
x0, x0 = xb, xb =
t;
1986 x2 = (int) x_bottom;
1988 y_crossing = (x1+1 -
x0) * dy + y_top;
1990 sign = e->direction;
1992 area = sign * (y_crossing-sy0);
1994 scanline[
x1] += area * (1-((x_top -
x1)+(x1+1-x1))/2);
1997 for (x = x1+1; x <
x2; ++
x) {
1998 scanline[
x] += area + step/2;
2001 y_crossing += dy * (x2 - (x1+1));
2005 scanline[
x2] += area + sign * (1-((x2-
x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
2007 scanline_fill[
x2] += sign * (sy1-sy0);
2015 for (x=0; x <
len; ++
x) {
2031 float x1 = (float) (x);
2032 float x2 = (float) (x+1);
2034 float y3 = y_bottom;
2040 y1 = (x -
x0) / dx + y_top;
2041 y2 = (x+1 -
x0) / dx + y_top;
2044 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
2045 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
2046 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
2047 }
else if (x3 < x1 && x0 > x2) {
2048 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
2049 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
2050 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
2052 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
2053 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
2054 }
else if (x3 < x1 && x0 > x1) {
2055 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
2056 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
2058 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
2059 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
2060 }
else if (x3 < x2 && x0 > x2) {
2061 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
2062 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
2064 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
2074 static void stbtt__rasterize_sorted_edges(
stbtt__bitmap *result, stbtt__edge *e,
int n,
int vsubsample,
int off_x,
int off_y,
void *userdata)
2077 stbtt__hheap hh = { 0, 0, 0 };
2078 stbtt__active_edge *active =
NULL;
2080 float scanline_data[129], *scanline, *scanline2;
2083 scanline = (
float *)
STBTT_malloc((result->
w*2+1) *
sizeof(float), userdata);
2085 scanline = scanline_data;
2087 scanline2 = scanline + result->
w;
2090 e[
n].y0 = (float) (off_y + result->
h) + 1;
2094 float scan_y_top = y + 0.0f;
2095 float scan_y_bottom = y + 1.0f;
2096 stbtt__active_edge **step = &active;
2098 STBTT_memset(scanline , 0, result->
w*
sizeof(scanline[0]));
2099 STBTT_memset(scanline2, 0, (result->
w+1)*
sizeof(scanline[0]));
2104 stbtt__active_edge *
z = *step;
2105 if (z->ey <= scan_y_top) {
2109 stbtt__hheap_free(&hh, z);
2111 step = &((*step)->next);
2116 while (e->y0 <= scan_y_bottom) {
2117 if (e->y0 != e->y1) {
2118 stbtt__active_edge *
z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
2131 stbtt__fill_active_edges_new(scanline, scanline2+1, result->
w, active, scan_y_top);
2135 for (i=0; i < result->
w; ++
i) {
2138 sum += scanline2[
i];
2139 k = scanline[
i] + sum;
2140 k = (float) STBTT_fabs(k)*255 + 0.5f;
2142 if (m > 255) m = 255;
2149 stbtt__active_edge *
z = *step;
2151 step = &((*step)->next);
2158 stbtt__hheap_cleanup(&hh, userdata);
2160 if (scanline != scanline_data)
2164 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 2167 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) 2169 static void stbtt__sort_edges_ins_sort(stbtt__edge *p,
int n)
2172 for (i=1; i <
n; ++
i) {
2173 stbtt__edge
t = p[
i], *
a = &
t;
2176 stbtt__edge *
b = &p[j-1];
2177 int c = STBTT__COMPARE(a,b);
2187 static void stbtt__sort_edges_quicksort(stbtt__edge *p,
int n)
2192 int c01,c12,
c,
m,
i,
j;
2196 c01 = STBTT__COMPARE(&p[0],&p[m]);
2197 c12 = STBTT__COMPARE(&p[m],&p[n-1]);
2202 c = STBTT__COMPARE(&p[0],&p[n-1]);
2205 z = (c == c12) ? 0 : n-1;
2223 if (!STBTT__COMPARE(&p[i], &p[0]))
break;
2226 if (!STBTT__COMPARE(&p[0], &p[j]))
break;
2239 stbtt__sort_edges_quicksort(p,j);
2243 stbtt__sort_edges_quicksort(p+i, n-i);
2249 static void stbtt__sort_edges(stbtt__edge *p,
int n)
2251 stbtt__sort_edges_quicksort(p, n);
2252 stbtt__sort_edges_ins_sort(p, n);
2260 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)
2262 float y_scale_inv = invert ? -scale_y : scale_y;
2265 #if STBTT_RASTERIZER_VERSION == 1 2266 int vsubsample = result->
h < 8 ? 15 : 5;
2267 #elif STBTT_RASTERIZER_VERSION == 2 2270 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 2276 for (i=0; i < windings; ++
i)
2279 e = (stbtt__edge *)
STBTT_malloc(
sizeof(*e) * (n+1), userdata);
2284 for (i=0; i < windings; ++
i) {
2285 stbtt__point *p = pts +
m;
2288 for (k=0; k < wcount[
i]; j=k++) {
2291 if (p[j].y == p[k].y)
2295 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
2299 e[
n].x0 = p[
a].x * scale_x + shift_x;
2300 e[
n].y0 = (p[
a].y * y_scale_inv + shift_y) * vsubsample;
2301 e[
n].x1 = p[
b].x * scale_x + shift_x;
2302 e[
n].y1 = (p[
b].y * y_scale_inv + shift_y) * vsubsample;
2309 stbtt__sort_edges(e, n);
2312 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
2317 static void stbtt__add_point(stbtt__point *
points,
int n,
float x,
float y)
2319 if (!points)
return;
2325 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)
2328 float mx = (x0 + 2*x1 +
x2)/4;
2329 float my = (y0 + 2*y1 +
y2)/4;
2331 float dx = (x0+
x2)/2 - mx;
2332 float dy = (y0+
y2)/2 - my;
2335 if (dx*dx+dy*dy > objspace_flatness_squared) {
2336 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0
f,(y0+y1)/2.0
f, mx,my, objspace_flatness_squared,n+1);
2337 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0
f,(y1+y2)/2.0
f, x2,y2, objspace_flatness_squared,n+1);
2339 stbtt__add_point(points, *num_points,x2,y2);
2340 *num_points = *num_points+1;
2346 static stbtt__point *stbtt_FlattenCurves(
stbtt_vertex *vertices,
int num_verts,
float objspace_flatness,
int **contour_lengths,
int *num_contours,
void *userdata)
2348 stbtt__point *points=0;
2351 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
2355 for (i=0; i < num_verts; ++
i)
2360 if (n == 0)
return 0;
2362 *contour_lengths = (
int *)
STBTT_malloc(
sizeof(**contour_lengths) *
n, userdata);
2364 if (*contour_lengths == 0) {
2370 for (pass=0; pass < 2; ++pass) {
2373 points = (stbtt__point *)
STBTT_malloc(num_points *
sizeof(points[0]), userdata);
2378 for (i=0; i < num_verts; ++
i) {
2379 switch (vertices[i].type) {
2383 (*contour_lengths)[
n] = num_points -
start;
2387 x = vertices[
i].
x, y = vertices[
i].
y;
2388 stbtt__add_point(points, num_points++, x,y);
2391 x = vertices[
i].
x, y = vertices[
i].
y;
2392 stbtt__add_point(points, num_points++, x, y);
2395 stbtt__tesselate_curve(points, &num_points, x,y,
2396 vertices[i].cx, vertices[i].cy,
2397 vertices[i].x, vertices[i].y,
2398 objspace_flatness_squared, 0);
2399 x = vertices[
i].
x, y = vertices[
i].
y;
2403 (*contour_lengths)[
n] = num_points -
start;
2410 *contour_lengths = 0;
2415 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)
2417 float scale = scale_x > scale_y ? scale_y : scale_x;
2418 int winding_count, *winding_lengths;
2419 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
2421 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
2434 int ix0,iy0,ix1,iy1;
2439 if (scale_x == 0) scale_x = scale_y;
2451 gbm.
w = (ix1 - ix0);
2452 gbm.
h = (iy1 - iy0);
2455 if (width ) *width = gbm.
w;
2456 if (height) *height = gbm.
h;
2457 if (xoff ) *xoff = ix0;
2458 if (yoff ) *yoff = iy0;
2460 if (gbm.
w && gbm.
h) {
2465 stbtt_Rasterize(&gbm, 0.35
f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->
userdata);
2491 stbtt_Rasterize(&gbm, 0.35
f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->
userdata);
2503 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y,
stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
2508 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y,
stbtt_FindGlyphIndex(info,codepoint));
2529 unsigned char *pixels,
int pw,
int ph,
2530 int first_char,
int num_chars,
2534 int x,
y,bottom_y,
i;
2539 STBTT_memset(pixels, 0, pw*ph);
2545 for (i=0; i < num_chars; ++
i) {
2552 if (x + gw + 1 >= pw)
2553 y = bottom_y, x = 1;
2554 if (y + gh + 1 >= ph)
2559 chardata[
i].
x0 = (stbtt_int16) x;
2560 chardata[
i].
y0 = (stbtt_int16) y;
2561 chardata[
i].
x1 = (stbtt_int16) (x + gw);
2562 chardata[
i].
y1 = (stbtt_int16) (y + gh);
2564 chardata[
i].
xoff = (float) x0;
2565 chardata[
i].
yoff = (float) y0;
2567 if (y+gh+1 > bottom_y)
2575 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
2576 float ipw = 1.0f / pw, iph = 1.0f / ph;
2578 int round_x = STBTT_ifloor((*xpos + b->
xoff) + 0.5f);
2579 int round_y = STBTT_ifloor((*ypos + b->
yoff) + 0.5f);
2581 q->
x0 = round_x + d3d_bias;
2582 q->
y0 = round_y + d3d_bias;
2583 q->
x1 = round_x + b->
x1 - b->
x0 + d3d_bias;
2584 q->
y1 = round_y + b->
y1 - b->
y0 + d3d_bias;
2586 q->
s0 = b->
x0 * ipw;
2587 q->
t0 = b->
y0 * iph;
2588 q->
s1 = b->
x1 * ipw;
2589 q->
t1 = b->
y1 * iph;
2599 #ifndef STB_RECT_PACK_VERSION 2601 #define STBTT__NOTUSED(v) (void)(v) 2603 #define STBTT__NOTUSED(v) (void)sizeof(v) 2633 int id,
w,
h,was_packed;
2643 STBTT__NOTUSED(nodes);
2644 STBTT__NOTUSED(num_nodes);
2650 for (i=0; i < num_rects; ++
i) {
2651 if (con->x + rects[i].
w > con->
width) {
2653 con->y = con->bottom_y;
2655 if (con->y + rects[i].
h > con->
height)
2657 rects[
i].
x = con->x;
2658 rects[
i].
y = con->y;
2660 con->x += rects[
i].
w;
2661 if (con->y + rects[i].
h > con->bottom_y)
2662 con->bottom_y = con->y + rects[
i].
h;
2664 for ( ; i < num_rects; ++
i)
2665 rects[i].was_packed = 0;
2682 if (context ==
NULL || nodes ==
NULL) {
2702 STBTT_memset(pixels, 0, pw*ph);
2717 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
2719 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
2723 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) 2725 static void stbtt__h_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
2727 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2728 int safe_w = w - kernel_width;
2730 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE);
2731 for (j=0; j <
h; ++
j) {
2734 STBTT_memset(buffer, 0, kernel_width);
2739 switch (kernel_width) {
2741 for (i=0; i <= safe_w; ++
i) {
2742 total += pixels[
i] - buffer[i & STBTT__OVER_MASK];
2743 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2744 pixels[
i] = (
unsigned char) (total / 2);
2748 for (i=0; i <= safe_w; ++
i) {
2749 total += pixels[
i] - buffer[i & STBTT__OVER_MASK];
2750 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2751 pixels[
i] = (
unsigned char) (total / 3);
2755 for (i=0; i <= safe_w; ++
i) {
2756 total += pixels[
i] - buffer[i & STBTT__OVER_MASK];
2757 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2758 pixels[
i] = (
unsigned char) (total / 4);
2762 for (i=0; i <= safe_w; ++
i) {
2763 total += pixels[
i] - buffer[i & STBTT__OVER_MASK];
2764 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2765 pixels[
i] = (
unsigned char) (total / 5);
2769 for (i=0; i <= safe_w; ++
i) {
2770 total += pixels[
i] - buffer[i & STBTT__OVER_MASK];
2771 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2772 pixels[
i] = (
unsigned char) (total / kernel_width);
2777 for (; i <
w; ++
i) {
2779 total -= buffer[i & STBTT__OVER_MASK];
2780 pixels[
i] = (
unsigned char) (total / kernel_width);
2787 static void stbtt__v_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
2789 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2790 int safe_h = h - kernel_width;
2792 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE);
2793 for (j=0; j <
w; ++
j) {
2796 STBTT_memset(buffer, 0, kernel_width);
2801 switch (kernel_width) {
2803 for (i=0; i <= safe_h; ++
i) {
2805 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2810 for (i=0; i <= safe_h; ++
i) {
2812 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2817 for (i=0; i <= safe_h; ++
i) {
2819 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2824 for (i=0; i <= safe_h; ++
i) {
2826 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2831 for (i=0; i <= safe_h; ++
i) {
2833 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2839 for (; i <
h; ++
i) {
2841 total -= buffer[i & STBTT__OVER_MASK];
2849 static float stbtt__oversample_shift(
int oversample)
2858 return (
float)-(oversample - 1) / (2.0
f * (
float)oversample);
2867 for (i=0; i < num_ranges; ++
i) {
2893 int i,
j,k, return_value = 1;
2900 for (i=0; i < num_ranges; ++
i) {
2903 float recip_h,recip_v,sub_x,sub_y;
2949 bc->
x0 = (stbtt_int16) r->
x;
2950 bc->
y0 = (stbtt_int16) r->
y;
2951 bc->
x1 = (stbtt_int16) (r->
x + r->
w);
2952 bc->
y1 = (stbtt_int16) (r->
y + r->
h);
2954 bc->
xoff = (float) x0 * recip_h + sub_x;
2955 bc->
yoff = (float) y0 * recip_v + sub_y;
2956 bc->
xoff2 = (x0 + r->
w) * recip_h + sub_x;
2957 bc->
yoff2 = (y0 + r->
h) * recip_v + sub_y;
2970 return return_value;
2981 int i,
j,
n, return_value = 1;
2986 for (i=0; i < num_ranges; ++
i)
2988 ranges[i].chardata_for_range[j].x0 =
2989 ranges[i].chardata_for_range[j].y0 =
2990 ranges[i].chardata_for_range[j].x1 =
2991 ranges[i].chardata_for_range[j].y1 = 0;
2994 for (i=0; i < num_ranges; ++
i)
2995 n += ranges[i].num_chars;
3011 return return_value;
3015 int first_unicode_codepoint_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range)
3028 float ipw = 1.0f / pw, iph = 1.0f / ph;
3031 if (align_to_integer) {
3032 float x = (float) STBTT_ifloor((*xpos + b->
xoff) + 0.5f);
3033 float y = (float) STBTT_ifloor((*ypos + b->
yoff) + 0.5f);
3045 q->
s0 = b->
x0 * ipw;
3046 q->
t0 = b->
y0 * iph;
3047 q->
s1 = b->
x1 * ipw;
3048 q->
t1 = b->
y1 * iph;
3060 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(
const stbtt_uint8 *
s1, stbtt_int32 len1,
const stbtt_uint8 *s2, stbtt_int32 len2)
3066 stbtt_uint16 ch = s2[0]*256 + s2[1];
3068 if (i >= len1)
return -1;
3069 if (s1[i++] != ch)
return -1;
3070 }
else if (ch < 0x800) {
3071 if (i+1 >= len1)
return -1;
3072 if (s1[i++] != 0xc0 + (ch >> 6))
return -1;
3073 if (s1[i++] != 0x80 + (ch & 0x3f))
return -1;
3074 }
else if (ch >= 0xd800 && ch < 0xdc00) {
3076 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
3077 if (i+3 >= len1)
return -1;
3078 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
3079 if (s1[i++] != 0xf0 + (c >> 18))
return -1;
3080 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f))
return -1;
3081 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f))
return -1;
3082 if (s1[i++] != 0x80 + ((c ) & 0x3f))
return -1;
3085 }
else if (ch >= 0xdc00 && ch < 0xe000) {
3088 if (i+2 >= len1)
return -1;
3089 if (s1[i++] != 0xe0 + (ch >> 12))
return -1;
3090 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f))
return -1;
3091 if (s1[i++] != 0x80 + ((ch ) & 0x3f))
return -1;
3101 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((
const stbtt_uint8*) s1, len1, (
const stbtt_uint8*) s2, len2);
3108 stbtt_int32
i,
count,stringOffset;
3109 stbtt_uint8 *fc = font->
data;
3111 stbtt_uint32 nm = stbtt__find_table(fc, offset,
"name");
3112 if (!nm)
return NULL;
3114 count = ttUSHORT(fc+nm+2);
3115 stringOffset = nm + ttUSHORT(fc+nm+4);
3116 for (i=0; i <
count; ++
i) {
3117 stbtt_uint32 loc = nm + 6 + 12 *
i;
3118 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
3119 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
3120 *length = ttUSHORT(fc+loc+8);
3121 return (
const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
3127 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *
name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
3130 stbtt_int32
count = ttUSHORT(fc+nm+2);
3131 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
3133 for (i=0; i <
count; ++
i) {
3134 stbtt_uint32 loc = nm + 6 + 12 *
i;
3135 stbtt_int32
id = ttUSHORT(fc+loc+6);
3136 if (
id == target_id) {
3138 stbtt_int32 platform = ttUSHORT(fc+loc+0),
encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
3141 if (platform == 0 || (platform == 3 &&
encoding == 1) || (platform == 3 &&
encoding == 10)) {
3142 stbtt_int32 slen = ttUSHORT(fc+loc+8);
3143 stbtt_int32 off = ttUSHORT(fc+loc+10);
3146 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
3147 if (matchlen >= 0) {
3149 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) {
3150 slen = ttUSHORT(fc+loc+12+8);
3151 off = ttUSHORT(fc+loc+12+10);
3153 if (matchlen == nlen)
3155 }
else if (matchlen < nlen && name[matchlen] ==
' ') {
3162 if (matchlen == nlen)
3174 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32
flags)
3176 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((
char *)
name);
3178 if (!stbtt__isfont(fc+offset))
return 0;
3182 hd = stbtt__find_table(fc, offset,
"head");
3183 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7))
return 0;
3186 nm = stbtt__find_table(fc, offset,
"name");
3191 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))
return 1;
3192 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1))
return 1;
3193 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
3195 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))
return 1;
3196 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2))
return 1;
3197 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
3208 if (off < 0)
return off;
3209 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
3214 #endif // STB_TRUETYPE_IMPLEMENTATION
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)
GLboolean GLboolean GLboolean b
boost_foreach_argument_dependent_lookup_hack tag
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)
typedef void(APIENTRY *GLDEBUGPROC)(GLenum source
GLuint const GLchar * name
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)
unsigned int v_oversample
STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices)
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLenum GLenum GLenum GLenum GLenum scale
GLdouble GLdouble GLdouble y2
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s0
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)
void * user_allocator_context
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
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_FreeBitmap(unsigned char *bitmap, void *userdata)
GLdouble GLdouble GLdouble w
unsigned int h_oversample
GLfloat GLfloat GLfloat GLfloat h
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)
struct stbrp_context stbrp_context
unsigned char v_oversample
GLboolean GLboolean GLboolean GLboolean a
unsigned short stbrp_coord
#define stbtt_vertex_type
def info(name, value, persistent=False)
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 const char * stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
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)
stbtt_packedchar * chardata_for_range
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)
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)
GLint GLsizei GLsizei height
GLint GLint GLsizei GLint GLenum format
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
#define GL_TEXTURE_MIN_FILTER
GLdouble GLdouble GLint stride
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
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
unsigned char h_oversample
int * array_of_unicode_codepoints
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)
void next(auto_any_t cur, type2type< T, C > *)
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
GLuint GLfloat GLfloat GLfloat x1
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
GLdouble GLdouble GLdouble q
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)
static const struct @18 vertices[3]
GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte * bitmap
#define STBTT_malloc(x, u)
STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
int first_unicode_codepoint_in_range
GLuint GLfloat GLfloat y0
STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
static const char * encoding
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)
STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
int main(int argv, const char **argc)
GLenum GLuint GLenum GLsizei length
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)
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels)
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
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)
STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, 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)
STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
GLdouble GLdouble GLint GLint const GLdouble * points