225 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
226 #include "stb_truetype.h"
228 char ttf_buffer[1<<20];
229 unsigned char temp_bitmap[512*512];
234 void my_stbtt_initfont(
void)
236 fread(ttf_buffer, 1, 1<<20, fopen(
"c:/windows/fonts/times.ttf",
"rb"));
239 glGenTextures(1, &ftex);
240 glBindTexture(GL_TEXTURE_2D, ftex);
241 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
246 void my_stbtt_print(
float x,
float y,
char *text)
249 glBindTexture(GL_TEXTURE_2D, ftex);
252 if (*text >= 32 && *text < 128) {
255 glTexCoord2f(q.
s0,q.
t1); glVertex2f(q.
x0,q.
y0);
256 glTexCoord2f(q.
s1,q.
t1); glVertex2f(q.
x1,q.
y0);
257 glTexCoord2f(q.
s1,q.
t0); glVertex2f(q.
x1,q.
y1);
258 glTexCoord2f(q.
s0,q.
t0); glVertex2f(q.
x0,q.
y1);
273 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
274 #include "stb_truetype.h"
276 char ttf_buffer[1<<25];
278 int main(
int argc,
char **argv)
281 unsigned char *bitmap;
282 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) :
'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
284 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] :
"c:/windows/fonts/arialbd.ttf",
"rb"));
289 for (j=0; j < h; ++j) {
290 for (i=0; i < w; ++i)
291 putchar(
" .:ioVM@"[bitmap[j*w+i]>>5]);
317 unsigned char screen[20][79];
319 int main(
int arg,
char **argv)
322 int i,j,ascent,baseline,ch=0;
324 char *text =
"Heljo World!";
326 fread(buffer, 1, 1000000, fopen(
"c:/windows/fonts/arialbd.ttf",
"rb"));
331 baseline = (int) (ascent*scale);
334 int advance,lsb,x0,y0,x1,y1;
335 float x_shift = xpos - (float) floor(xpos);
343 xpos += (advance *
scale);
349 for (j=0; j < 20; ++j) {
350 for (i=0; i < 78; ++i)
351 putchar(
" .:ioVM@"[screen[j][i]>>5]);
368 #ifdef STB_TRUETYPE_IMPLEMENTATION
371 typedef unsigned char stbtt_uint8;
372 typedef signed char stbtt_int8;
373 typedef unsigned short stbtt_uint16;
374 typedef signed short stbtt_int16;
375 typedef unsigned int stbtt_uint32;
376 typedef signed int stbtt_int32;
379 typedef char stbtt__check_size32[
sizeof(stbtt_int32)==4 ? 1 : -1];
380 typedef char stbtt__check_size16[
sizeof(stbtt_int16)==2 ? 1 : -1];
383 #define STBTT_DEF static
385 #define STBTT_DEF extern
391 #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
397 #define STBTT_ifloor(x) ((int) floor(x))
398 #define STBTT_iceil(x) ((int) ceil(x))
403 #define STBTT_sqrt(x) sqrt(x)
409 #define STBTT_malloc(x,u) ((void)(u),malloc(x))
410 #define STBTT_free(x,u) ((void)(u),free(x))
415 #define STBTT_assert(x) assert(x)
420 #define STBTT_strlen(x) strlen(x)
425 #define STBTT_memcpy memcpy
426 #define STBTT_memset memset
437 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
438 #define __STB_INCLUDE_STB_TRUETYPE_H__
453 unsigned short x0,y0,x1,
y1;
459 unsigned char *pixels,
int pw,
int ph,
460 int first_char,
int num_chars,
475 float *xpos,
float *ypos,
477 int opengl_fillrule);
499 unsigned short x0,y0,x1,
y1;
506 #ifndef STB_RECT_PACK_VERSION
524 #define STBTT_POINT_SIZE(x) (-(x))
527 int first_unicode_char_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range);
575 float *xpos,
float *ypos,
577 int align_to_integer);
694 #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
702 #ifndef stbtt_vertex // you can predefine this to use different values
704 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
789 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);
818 #define STBTT_MACSTYLE_DONTCARE 0
819 #define STBTT_MACSTYLE_BOLD 1
820 #define STBTT_MACSTYLE_ITALIC 2
821 #define STBTT_MACSTYLE_UNDERSCORE 4
822 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
889 #endif // __STB_INCLUDE_STB_TRUETYPE_H__
898 #ifdef STB_TRUETYPE_IMPLEMENTATION
900 #ifndef STBTT_MAX_OVERSAMPLE
901 #define STBTT_MAX_OVERSAMPLE 8
904 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
914 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
915 #define ttCHAR(p) (* (stbtt_int8 *) (p))
916 #define ttFixed(p) ttLONG(p)
918 #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
920 #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
921 #define ttSHORT(p) (* (stbtt_int16 *) (p))
922 #define ttULONG(p) (* (stbtt_uint32 *) (p))
923 #define ttLONG(p) (* (stbtt_int32 *) (p))
927 static stbtt_uint16 ttUSHORT(
const stbtt_uint8 *p) {
return p[0]*256 + p[1]; }
928 static stbtt_int16 ttSHORT(
const stbtt_uint8 *p) {
return p[0]*256 + p[1]; }
929 static stbtt_uint32 ttULONG(
const stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
930 static stbtt_int32 ttLONG(
const stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
934 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
935 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
937 static int stbtt__isfont(
const stbtt_uint8 *font)
940 if (stbtt_tag4(font,
'1',0,0,0))
return 1;
941 if (stbtt_tag(font,
"typ1"))
return 1;
942 if (stbtt_tag(font,
"OTTO"))
return 1;
943 if (stbtt_tag4(font, 0,1,0,0))
return 1;
948 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart,
const char *tag)
950 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
951 stbtt_uint32 tabledir = fontstart + 12;
953 for (i=0; i < num_tables; ++i) {
954 stbtt_uint32 loc = tabledir + 16*i;
955 if (stbtt_tag(data+loc+0, tag))
956 return ttULONG(data+loc+8);
964 if (stbtt__isfont(font_collection))
965 return index == 0 ? 0 : -1;
968 if (stbtt_tag(font_collection,
"ttcf")) {
970 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
971 stbtt_int32 n = ttLONG(font_collection+8);
974 return ttULONG(font_collection+12+index*14);
982 stbtt_uint8 *data = (stbtt_uint8 *) data2;
983 stbtt_uint32 cmap, t;
984 stbtt_int32 i,numTables;
989 cmap = stbtt__find_table(data, fontstart,
"cmap");
990 info->
loca = stbtt__find_table(data, fontstart,
"loca");
991 info->
head = stbtt__find_table(data, fontstart,
"head");
992 info->
glyf = stbtt__find_table(data, fontstart,
"glyf");
993 info->
hhea = stbtt__find_table(data, fontstart,
"hhea");
994 info->
hmtx = stbtt__find_table(data, fontstart,
"hmtx");
995 info->
kern = stbtt__find_table(data, fontstart,
"kern");
999 t = stbtt__find_table(data, fontstart,
"maxp");
1008 numTables = ttUSHORT(data + cmap + 2);
1010 for (i=0; i < numTables; ++i) {
1011 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
1013 switch(ttUSHORT(data+encoding_record)) {
1015 switch (ttUSHORT(data+encoding_record+2)) {
1019 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1026 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1039 stbtt_uint8 *data = info->
data;
1040 stbtt_uint32 index_map = info->
index_map;
1042 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1044 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1045 if (unicode_codepoint < bytes-6)
1046 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1048 }
else if (format == 6) {
1049 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1050 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1051 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1052 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1054 }
else if (format == 2) {
1057 }
else if (format == 4) {
1058 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1059 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1060 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1061 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1062 stbtt_uint16 item, offset, start, end;
1065 stbtt_uint32 endCount = index_map + 14;
1066 stbtt_uint32 search = endCount;
1068 if (unicode_codepoint > 0xffff)
1073 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1074 search += rangeShift*2;
1078 while (entrySelector) {
1080 start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
1081 end = ttUSHORT(data + search + searchRange*2);
1082 if (unicode_codepoint > end)
1083 search += searchRange*2;
1088 item = (stbtt_uint16) ((search - endCount) >> 1);
1090 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1091 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1092 end = ttUSHORT(data + index_map + 14 + 2 + 2*item);
1093 if (unicode_codepoint < start)
1096 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1098 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1100 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1101 }
else if (format == 12 || format == 13) {
1102 stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1103 stbtt_int32 low,high;
1104 low = 0; high = (stbtt_int32)ngroups;
1106 while (low < high) {
1107 stbtt_int32 mid = low + ((high-low) >> 1);
1108 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1109 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1110 if ((stbtt_uint32) unicode_codepoint < start_char)
1112 else if ((stbtt_uint32) unicode_codepoint > end_char)
1115 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1117 return start_glyph + unicode_codepoint-start_char;
1134 static void stbtt_setvertex(
stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1137 v->
x = (stbtt_int16) x;
1138 v->
y = (stbtt_int16) y;
1139 v->
cx = (stbtt_int16) cx;
1140 v->
cy = (stbtt_int16) cy;
1143 static int stbtt__GetGlyfOffset(
const stbtt_fontinfo *info,
int glyph_index)
1147 if (glyph_index >= info->
numGlyphs)
return -1;
1151 g1 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2) * 2;
1152 g2 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2 + 2) * 2;
1154 g1 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4);
1155 g2 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4 + 4);
1158 return g1==g2 ? -1 : g1;
1163 int g = stbtt__GetGlyfOffset(info, glyph_index);
1164 if (g < 0)
return 0;
1166 if (x0) *x0 = ttSHORT(info->
data + g + 2);
1167 if (y0) *y0 = ttSHORT(info->
data + g + 4);
1168 if (x1) *x1 = ttSHORT(info->
data + g + 6);
1169 if (y1) *y1 = ttSHORT(info->
data + g + 8);
1180 stbtt_int16 numberOfContours;
1181 int g = stbtt__GetGlyfOffset(info, glyph_index);
1182 if (g < 0)
return 1;
1183 numberOfContours = ttSHORT(info->
data + g);
1184 return numberOfContours == 0;
1187 static int stbtt__close_shape(
stbtt_vertex *vertices,
int num_vertices,
int was_off,
int start_off,
1188 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1192 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1193 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, sx,sy,scx,scy);
1196 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve,sx,sy,cx,cy);
1198 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline,sx,sy,0,0);
1200 return num_vertices;
1205 stbtt_int16 numberOfContours;
1206 stbtt_uint8 *endPtsOfContours;
1207 stbtt_uint8 *data = info->
data;
1210 int g = stbtt__GetGlyfOffset(info, glyph_index);
1214 if (g < 0)
return 0;
1216 numberOfContours = ttSHORT(data + g);
1218 if (numberOfContours > 0) {
1219 stbtt_uint8 flags=0,flagcount;
1220 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1221 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1222 stbtt_uint8 *points;
1223 endPtsOfContours = (data + g + 10);
1224 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1225 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1227 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1229 m = n + 2*numberOfContours;
1245 for (i=0; i < n; ++i) {
1246 if (flagcount == 0) {
1249 flagcount = *points++;
1252 vertices[off+i].
type = flags;
1257 for (i=0; i < n; ++i) {
1258 flags = vertices[off+i].
type;
1260 stbtt_int16 dx = *points++;
1261 x += (flags & 16) ? dx : -dx;
1263 if (!(flags & 16)) {
1264 x = x + (stbtt_int16) (points[0]*256 + points[1]);
1268 vertices[off+i].
x = (stbtt_int16) x;
1273 for (i=0; i < n; ++i) {
1274 flags = vertices[off+i].
type;
1276 stbtt_int16 dy = *points++;
1277 y += (flags & 32) ? dy : -dy;
1279 if (!(flags & 32)) {
1280 y = y + (stbtt_int16) (points[0]*256 + points[1]);
1284 vertices[off+i].
y = (stbtt_int16) y;
1289 sx = sy = cx = cy = scx = scy = 0;
1290 for (i=0; i < n; ++i) {
1291 flags = vertices[off+i].
type;
1292 x = (stbtt_int16) vertices[off+i].x;
1293 y = (stbtt_int16) vertices[off+i].y;
1295 if (next_move == i) {
1297 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1300 start_off = !(flags & 1);
1306 if (!(vertices[off+i+1].type & 1)) {
1308 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1309 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1312 sx = (stbtt_int32) vertices[off+i+1].x;
1313 sy = (stbtt_int32) vertices[off+i+1].y;
1320 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vmove,sx,sy,0,0);
1322 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1327 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1333 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, x,y, cx, cy);
1335 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline, x,y,0,0);
1340 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1341 }
else if (numberOfContours == -1) {
1344 stbtt_uint8 *comp = data + g + 10;
1348 stbtt_uint16 flags, gidx;
1349 int comp_num_verts = 0, i;
1351 float mtx[6] = {1,0,0,1,0,0}, m, n;
1353 flags = ttSHORT(comp); comp+=2;
1354 gidx = ttSHORT(comp); comp+=2;
1358 mtx[4] = ttSHORT(comp); comp+=2;
1359 mtx[5] = ttSHORT(comp); comp+=2;
1361 mtx[4] = ttCHAR(comp); comp+=1;
1362 mtx[5] = ttCHAR(comp); comp+=1;
1369 if (flags & (1<<3)) {
1370 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1371 mtx[1] = mtx[2] = 0;
1372 }
else if (flags & (1<<6)) {
1373 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1374 mtx[1] = mtx[2] = 0;
1375 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1376 }
else if (flags & (1<<7)) {
1377 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1378 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1379 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1380 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1384 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1385 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1389 if (comp_num_verts > 0) {
1391 for (i = 0; i < comp_num_verts; ++i) {
1408 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*
sizeof(
stbtt_vertex));
1409 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*
sizeof(
stbtt_vertex));
1413 num_vertices += comp_num_verts;
1416 more = flags & (1<<5);
1418 }
else if (numberOfContours < 0) {
1425 *pvertices = vertices;
1426 return num_vertices;
1431 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->
data+info->
hhea + 34);
1432 if (glyph_index < numOfLongHorMetrics) {
1433 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*glyph_index);
1434 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*glyph_index + 2);
1436 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*(numOfLongHorMetrics-1));
1437 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
1443 stbtt_uint8 *data = info->
data + info->
kern;
1444 stbtt_uint32 needle, straw;
1450 if (ttUSHORT(data+2) < 1)
1452 if (ttUSHORT(data+8) != 1)
1456 r = ttUSHORT(data+10) - 1;
1457 needle = glyph1 << 16 | glyph2;
1460 straw = ttULONG(data+18+(m*6));
1463 else if (needle > straw)
1466 return ttSHORT(data+22+(m*6));
1485 if (ascent ) *ascent = ttSHORT(info->
data+info->
hhea + 4);
1486 if (descent) *descent = ttSHORT(info->
data+info->
hhea + 6);
1487 if (lineGap) *lineGap = ttSHORT(info->
data+info->
hhea + 8);
1492 *x0 = ttSHORT(info->
data + info->
head + 36);
1493 *y0 = ttSHORT(info->
data + info->
head + 38);
1494 *x1 = ttSHORT(info->
data + info->
head + 40);
1495 *y1 = ttSHORT(info->
data + info->
head + 42);
1500 int fheight = ttSHORT(info->
data + info->
hhea + 4) - ttSHORT(info->
data + info->
hhea + 6);
1501 return (
float) height / fheight;
1506 int unitsPerEm = ttUSHORT(info->
data + info->
head + 18);
1507 return pixels / unitsPerEm;
1531 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
1532 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
1533 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
1534 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
1545 stbtt_GetGlyphBitmapBoxSubpixel(font,
stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
1553 typedef struct stbtt__edge {
1558 typedef struct stbtt__active_edge
1562 struct stbtt__active_edge *next;
1564 } stbtt__active_edge;
1567 #define FIX (1 << FIXSHIFT)
1568 #define FIXMASK (FIX-1)
1570 static stbtt__active_edge *new_active(stbtt__edge *e,
int off_x,
float start_point,
void *userdata)
1572 stbtt__active_edge *z = (stbtt__active_edge *)
STBTT_malloc(
sizeof(*z), userdata);
1573 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
1578 z->dx = -STBTT_ifloor(FIX * -dxdy);
1580 z->dx = STBTT_ifloor(FIX * dxdy);
1581 z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
1582 z->x -= off_x * FIX;
1585 z->valid = e->invert ? 1 : -1;
1592 static void stbtt__fill_active_edges(
unsigned char *scanline,
int len, stbtt__active_edge *e,
int max_weight)
1600 x0 = e->x; w += e->valid;
1602 int x1 = e->x; w += e->valid;
1605 int i = x0 >> FIXSHIFT;
1606 int j = x1 >> FIXSHIFT;
1608 if (i < len && j >= 0) {
1611 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
1614 scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
1619 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
1623 for (++i; i < j; ++i)
1624 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
1634 static void stbtt__rasterize_sorted_edges(
stbtt__bitmap *result, stbtt__edge *e,
int n,
int vsubsample,
int off_x,
int off_y,
void *userdata)
1636 stbtt__active_edge *active = NULL;
1638 int max_weight = (255 / vsubsample);
1640 unsigned char scanline_data[512], *scanline;
1642 if (result->
w > 512)
1643 scanline = (
unsigned char *)
STBTT_malloc(result->
w, userdata);
1645 scanline = scanline_data;
1647 y = off_y * vsubsample;
1648 e[n].y0 = (off_y + result->
h) * (
float) vsubsample + 1;
1650 while (j < result->h) {
1651 STBTT_memset(scanline, 0, result->
w);
1652 for (s=0; s < vsubsample; ++s) {
1654 float scan_y = y + 0.5f;
1655 stbtt__active_edge **step = &active;
1660 stbtt__active_edge * z = *step;
1661 if (z->ey <= scan_y) {
1668 step = &((*step)->next);
1676 while (*step && (*step)->next) {
1677 if ((*step)->x > (*step)->next->x) {
1678 stbtt__active_edge *t = *step;
1679 stbtt__active_edge *q = t->next;
1686 step = &(*step)->next;
1688 if (!changed)
break;
1692 while (e->y0 <= scan_y) {
1693 if (e->y1 > scan_y) {
1694 stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
1698 else if (z->x < active->x) {
1704 stbtt__active_edge *p = active;
1705 while (p->next && p->next->x < z->x)
1717 stbtt__fill_active_edges(scanline, result->
w, active, max_weight);
1721 STBTT_memcpy(result->
pixels + j * result->
stride, scanline, result->
w);
1726 stbtt__active_edge *z = active;
1727 active = active->next;
1731 if (scanline != scanline_data)
1735 static int stbtt__edge_compare(
const void *p,
const void *q)
1737 stbtt__edge *a = (stbtt__edge *) p;
1738 stbtt__edge *b = (stbtt__edge *) q;
1740 if (a->y0 < b->y0)
return -1;
1741 if (a->y0 > b->y0)
return 1;
1750 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)
1752 float y_scale_inv = invert ? -scale_y : scale_y;
1755 int vsubsample = result->
h < 8 ? 15 : 5;
1760 for (i=0; i < windings; ++i)
1763 e = (stbtt__edge *)
STBTT_malloc(
sizeof(*e) * (n+1), userdata);
1768 for (i=0; i < windings; ++i) {
1769 stbtt__point *p = pts + m;
1772 for (k=0; k < wcount[i]; j=k++) {
1775 if (p[j].y == p[k].y)
1779 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
1783 e[n].x0 = p[a].x * scale_x + shift_x;
1784 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
1785 e[n].x1 = p[b].x * scale_x + shift_x;
1786 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
1792 STBTT_sort(e, n,
sizeof(e[0]), stbtt__edge_compare);
1795 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
1800 static void stbtt__add_point(stbtt__point *points,
int n,
float x,
float y)
1802 if (!points)
return;
1808 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)
1811 float mx = (x0 + 2*x1 + x2)/4;
1812 float my = (y0 + 2*y1 + y2)/4;
1814 float dx = (x0+x2)/2 - mx;
1815 float dy = (y0+y2)/2 - my;
1818 if (dx*dx+dy*dy > objspace_flatness_squared) {
1819 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
1820 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
1822 stbtt__add_point(points, *num_points,x2,y2);
1823 *num_points = *num_points+1;
1829 static stbtt__point *stbtt_FlattenCurves(
stbtt_vertex *vertices,
int num_verts,
float objspace_flatness,
int **contour_lengths,
int *num_contours,
void *userdata)
1831 stbtt__point *points=0;
1834 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
1835 int i,n=0,start=0, pass;
1838 for (i=0; i < num_verts; ++i)
1843 if (n == 0)
return 0;
1845 *contour_lengths = (
int *)
STBTT_malloc(
sizeof(**contour_lengths) * n, userdata);
1847 if (*contour_lengths == 0) {
1853 for (pass=0; pass < 2; ++pass) {
1856 points = (stbtt__point *)
STBTT_malloc(num_points *
sizeof(points[0]), userdata);
1857 if (points == NULL)
goto error;
1861 for (i=0; i < num_verts; ++i) {
1862 switch (vertices[i].type) {
1866 (*contour_lengths)[n] = num_points - start;
1870 x = vertices[i].
x, y = vertices[i].
y;
1871 stbtt__add_point(points, num_points++, x,y);
1874 x = vertices[i].
x, y = vertices[i].
y;
1875 stbtt__add_point(points, num_points++, x, y);
1878 stbtt__tesselate_curve(points, &num_points, x,y,
1879 vertices[i].cx, vertices[i].cy,
1880 vertices[i].x, vertices[i].y,
1881 objspace_flatness_squared, 0);
1882 x = vertices[i].
x, y = vertices[i].
y;
1886 (*contour_lengths)[n] = num_points - start;
1893 *contour_lengths = 0;
1898 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)
1900 float scale = scale_x > scale_y ? scale_y : scale_x;
1901 int winding_count, *winding_lengths;
1902 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
1904 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
1917 int ix0,iy0,ix1,iy1;
1922 if (scale_x == 0) scale_x = scale_y;
1924 if (scale_x == 0)
return NULL;
1931 gbm.
w = (ix1 - ix0);
1932 gbm.
h = (iy1 - iy0);
1935 if (width ) *width = gbm.
w;
1936 if (height) *height = gbm.
h;
1937 if (xoff ) *xoff = ix0;
1938 if (yoff ) *yoff = iy0;
1940 if (gbm.
w && gbm.
h) {
1945 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->
userdata);
1971 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->
userdata);
1983 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y,
stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
1988 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y,
stbtt_FindGlyphIndex(info,codepoint));
2009 unsigned char *pixels,
int pw,
int ph,
2010 int first_char,
int num_chars,
2014 int x,y,bottom_y, i;
2018 STBTT_memset(pixels, 0, pw*ph);
2024 for (i=0; i < num_chars; ++i) {
2025 int advance, lsb, x0,y0,x1,y1,gw,gh;
2031 if (x + gw + 1 >= pw)
2032 y = bottom_y, x = 1;
2033 if (y + gh + 1 >= ph)
2038 chardata[i].
x0 = (stbtt_int16) x;
2039 chardata[i].
y0 = (stbtt_int16) y;
2040 chardata[i].
x1 = (stbtt_int16) (x + gw);
2041 chardata[i].
y1 = (stbtt_int16) (y + gh);
2042 chardata[i].
xadvance = scale * advance;
2043 chardata[i].
xoff = (float) x0;
2044 chardata[i].
yoff = (float) y0;
2046 if (y+gh+1 > bottom_y)
2054 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
2055 float ipw = 1.0f / pw, iph = 1.0f / ph;
2057 int round_x = STBTT_ifloor((*xpos + b->
xoff) + 0.5);
2058 int round_y = STBTT_ifloor((*ypos + b->
yoff) + 0.5);
2060 q->
x0 = round_x + d3d_bias;
2061 q->
y0 = round_y + d3d_bias;
2062 q->
x1 = round_x + b->
x1 - b->
x0 + d3d_bias;
2063 q->
y1 = round_y + b->
y1 - b->
y0 + d3d_bias;
2065 q->
s0 = b->
x0 * ipw;
2066 q->
t0 = b->
y0 * iph;
2067 q->
s1 = b->
x1 * ipw;
2068 q->
t1 = b->
y1 * iph;
2078 #ifndef STB_RECT_PACK_VERSION
2080 #define STBTT__NOTUSED(v) (void)(v)
2082 #define STBTT__NOTUSED(v) (void)sizeof(v)
2122 STBTT__NOTUSED(nodes);
2123 STBTT__NOTUSED(num_nodes);
2129 for (i=0; i < num_rects; ++i) {
2130 if (con->x + rects[i].
w > con->
width) {
2132 con->y = con->bottom_y;
2134 if (con->y + rects[i].
h > con->
height)
2136 rects[i].
x = con->x;
2137 rects[i].
y = con->y;
2139 con->x += rects[i].
w;
2140 if (con->y + rects[i].
h > con->bottom_y)
2141 con->bottom_y = con->y + rects[i].
h;
2143 for ( ; i < num_rects; ++i)
2144 rects[i].was_packed = 0;
2158 int num_nodes = pw - padding;
2161 if (context == NULL || nodes == NULL) {
2162 if (context != NULL)
STBTT_free(context, alloc_context);
2163 if (nodes != NULL)
STBTT_free(nodes , alloc_context);
2181 STBTT_memset(pixels, 0, pw*ph);
2196 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
2198 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
2202 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
2204 static void stbtt__h_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
2206 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2207 int safe_w = w - kernel_width;
2209 for (j=0; j < h; ++j) {
2212 memset(buffer, 0, kernel_width);
2217 switch (kernel_width) {
2219 for (i=0; i <= safe_w; ++i) {
2220 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2221 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2222 pixels[i] = (
unsigned char) (total / 2);
2226 for (i=0; i <= safe_w; ++i) {
2227 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2228 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2229 pixels[i] = (
unsigned char) (total / 3);
2233 for (i=0; i <= safe_w; ++i) {
2234 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2235 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2236 pixels[i] = (
unsigned char) (total / 4);
2240 for (i=0; i <= safe_w; ++i) {
2241 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2242 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2243 pixels[i] = (
unsigned char) (total / kernel_width);
2248 for (; i < w; ++i) {
2250 total -= buffer[i & STBTT__OVER_MASK];
2251 pixels[i] = (
unsigned char) (total / kernel_width);
2254 pixels += stride_in_bytes;
2258 static void stbtt__v_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
2260 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2261 int safe_h = h - kernel_width;
2263 for (j=0; j < w; ++j) {
2266 memset(buffer, 0, kernel_width);
2271 switch (kernel_width) {
2273 for (i=0; i <= safe_h; ++i) {
2274 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2275 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2276 pixels[i*stride_in_bytes] = (
unsigned char) (total / 2);
2280 for (i=0; i <= safe_h; ++i) {
2281 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2282 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2283 pixels[i*stride_in_bytes] = (
unsigned char) (total / 3);
2287 for (i=0; i <= safe_h; ++i) {
2288 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2289 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2290 pixels[i*stride_in_bytes] = (
unsigned char) (total / 4);
2294 for (i=0; i <= safe_h; ++i) {
2295 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2296 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2297 pixels[i*stride_in_bytes] = (
unsigned char) (total / kernel_width);
2302 for (; i < h; ++i) {
2304 total -= buffer[i & STBTT__OVER_MASK];
2305 pixels[i*stride_in_bytes] = (
unsigned char) (total / kernel_width);
2312 static float stbtt__oversample_shift(
int oversample)
2321 return (
float)-(oversample - 1) / (2.0f * (
float)oversample);
2330 for (i=0; i < num_ranges; ++i) {
2345 rects[k].
w = rects[k].
h = 1;
2359 float sub_x = stbtt__oversample_shift(spc->
h_oversample);
2360 float sub_y = stbtt__oversample_shift(spc->
v_oversample);
2361 int i,j,k, return_value = 1;
2364 for (i=0; i < num_ranges; ++i) {
2371 int advance, lsb, x0,y0,x1,y1;
2405 bc->
x0 = (stbtt_int16) r->
x;
2406 bc->
y0 = (stbtt_int16) r->
y;
2407 bc->
x1 = (stbtt_int16) (r->
x + r->
w);
2408 bc->
y1 = (stbtt_int16) (r->
y + r->
h);
2410 bc->
xoff = (float) x0 * recip_h + sub_x;
2411 bc->
yoff = (float) y0 * recip_v + sub_y;
2412 bc->
xoff2 = (x0 + r->
w) * recip_h + sub_x;
2413 bc->
yoff2 = (y0 + r->
h) * recip_v + sub_y;
2422 return return_value;
2428 int i,j,n, return_value = 1;
2433 for (i=0; i < num_ranges; ++i)
2435 ranges[i].chardata_for_range[j].x0 =
2436 ranges[i].chardata_for_range[j].y0 =
2437 ranges[i].chardata_for_range[j].x1 =
2438 ranges[i].chardata_for_range[j].y1 = 0;
2441 for (i=0; i < num_ranges; ++i)
2442 n += ranges[i].num_chars_in_range;
2456 return return_value;
2460 int first_unicode_char_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range)
2472 float ipw = 1.0f / pw, iph = 1.0f / ph;
2475 if (align_to_integer) {
2476 float x = (float) STBTT_ifloor((*xpos + b->
xoff) + 0.5);
2477 float y = (float) STBTT_ifloor((*ypos + b->
yoff) + 0.5);
2489 q->
s0 = b->
x0 * ipw;
2490 q->
t0 = b->
y0 * iph;
2491 q->
s1 = b->
x1 * ipw;
2492 q->
t1 = b->
y1 * iph;
2504 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(
const stbtt_uint8 *s1, stbtt_int32 len1,
const stbtt_uint8 *s2, stbtt_int32 len2)
2510 stbtt_uint16 ch = s2[0]*256 + s2[1];
2512 if (i >= len1)
return -1;
2513 if (s1[i++] != ch)
return -1;
2514 }
else if (ch < 0x800) {
2515 if (i+1 >= len1)
return -1;
2516 if (s1[i++] != 0xc0 + (ch >> 6))
return -1;
2517 if (s1[i++] != 0x80 + (ch & 0x3f))
return -1;
2518 }
else if (ch >= 0xd800 && ch < 0xdc00) {
2520 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
2521 if (i+3 >= len1)
return -1;
2522 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
2523 if (s1[i++] != 0xf0 + (c >> 18))
return -1;
2524 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f))
return -1;
2525 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f))
return -1;
2526 if (s1[i++] != 0x80 + ((c ) & 0x3f))
return -1;
2529 }
else if (ch >= 0xdc00 && ch < 0xe000) {
2532 if (i+2 >= len1)
return -1;
2533 if (s1[i++] != 0xe0 + (ch >> 12))
return -1;
2534 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f))
return -1;
2535 if (s1[i++] != 0x80 + ((ch ) & 0x3f))
return -1;
2545 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((
const stbtt_uint8*) s1, len1, (
const stbtt_uint8*) s2, len2);
2552 stbtt_int32 i,count,stringOffset;
2553 stbtt_uint8 *fc = font->
data;
2555 stbtt_uint32 nm = stbtt__find_table(fc, offset,
"name");
2556 if (!nm)
return NULL;
2558 count = ttUSHORT(fc+nm+2);
2559 stringOffset = nm + ttUSHORT(fc+nm+4);
2560 for (i=0; i < count; ++i) {
2561 stbtt_uint32 loc = nm + 6 + 12 * i;
2562 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
2563 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
2564 *length = ttUSHORT(fc+loc+8);
2565 return (
const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
2571 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
2574 stbtt_int32 count = ttUSHORT(fc+nm+2);
2575 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
2577 for (i=0; i < count; ++i) {
2578 stbtt_uint32 loc = nm + 6 + 12 * i;
2579 stbtt_int32
id = ttUSHORT(fc+loc+6);
2580 if (
id == target_id) {
2582 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
2585 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
2586 stbtt_int32 slen = ttUSHORT(fc+loc+8);
2587 stbtt_int32 off = ttUSHORT(fc+loc+10);
2590 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
2591 if (matchlen >= 0) {
2593 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) {
2594 slen = ttUSHORT(fc+loc+12+8);
2595 off = ttUSHORT(fc+loc+12+10);
2597 if (matchlen == nlen)
2599 }
else if (matchlen < nlen && name[matchlen] ==
' ') {
2606 if (matchlen == nlen)
2618 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
2620 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((
char *) name);
2622 if (!stbtt__isfont(fc+offset))
return 0;
2626 hd = stbtt__find_table(fc, offset,
"head");
2627 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7))
return 0;
2630 nm = stbtt__find_table(fc, offset,
"name");
2635 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))
return 1;
2636 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1))
return 1;
2637 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
2639 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))
return 1;
2640 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2))
return 1;
2641 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
2647 STBTT_DEF
int stbtt_FindMatchingFont(
const unsigned char *font_collection,
const char *name_utf8, stbtt_int32 flags)
2652 if (off < 0)
return off;
2653 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
2658 #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)
unsigned int h_oversample
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)
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
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 void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
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 void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
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)
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
#define STBTT_malloc(x, u)
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_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
stbtt_packedchar * chardata_for_range
STBTT_DEF const char * stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
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)
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices)
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)
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
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)
#define stbtt_vertex_type
STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels)
static void error(char *msg)
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)
STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
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 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_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)
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, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
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_PackEnd(stbtt_pack_context *spc)
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices)
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
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)
void * user_allocator_context
STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
int first_unicode_char_in_range
unsigned short stbrp_coord
int main(int argc, char *argv[])
unsigned int v_oversample
STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
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)
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)