222 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
223 #include "stb_truetype.h"
225 char ttf_buffer[1<<20];
226 unsigned char temp_bitmap[512*512];
231 void my_stbtt_initfont(
void)
233 fread(ttf_buffer, 1, 1<<20, fopen(
"c:/windows/fonts/times.ttf",
"rb"));
236 glGenTextures(1, &ftex);
237 glBindTexture(GL_TEXTURE_2D, ftex);
238 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
243 void my_stbtt_print(
float x,
float y,
char *text)
246 glBindTexture(GL_TEXTURE_2D, ftex);
249 if (*text >= 32 && *text < 128) {
252 glTexCoord2f(q.
s0,q.
t1); glVertex2f(q.
x0,q.
y0);
253 glTexCoord2f(q.
s1,q.
t1); glVertex2f(q.
x1,q.
y0);
254 glTexCoord2f(q.
s1,q.
t0); glVertex2f(q.
x1,q.
y1);
255 glTexCoord2f(q.
s0,q.
t0); glVertex2f(q.
x0,q.
y1);
270 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
271 #include "stb_truetype.h"
273 char ttf_buffer[1<<25];
275 int main(
int argc,
char **argv)
278 unsigned char *bitmap;
279 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) :
'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
281 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] :
"c:/windows/fonts/arialbd.ttf",
"rb"));
286 for (j=0; j < h; ++j) {
287 for (i=0; i < w; ++i)
288 putchar(
" .:ioVM@"[bitmap[j*w+i]>>5]);
314 unsigned char screen[20][79];
316 int main(
int arg,
char **argv)
319 int i,j,ascent,baseline,ch=0;
321 char *text =
"Heljo World!";
323 fread(buffer, 1, 1000000, fopen(
"c:/windows/fonts/arialbd.ttf",
"rb"));
328 baseline = (int) (ascent*scale);
331 int advance,lsb,x0,y0,x1,y1;
332 float x_shift = xpos - (float) floor(xpos);
340 xpos += (advance *
scale);
346 for (j=0; j < 20; ++j) {
347 for (i=0; i < 78; ++i)
348 putchar(
" .:ioVM@"[screen[j][i]>>5]);
365 #ifdef STB_TRUETYPE_IMPLEMENTATION
368 typedef unsigned char stbtt_uint8;
369 typedef signed char stbtt_int8;
370 typedef unsigned short stbtt_uint16;
371 typedef signed short stbtt_int16;
372 typedef unsigned int stbtt_uint32;
373 typedef signed int stbtt_int32;
376 typedef char stbtt__check_size32[
sizeof(stbtt_int32)==4 ? 1 : -1];
377 typedef char stbtt__check_size16[
sizeof(stbtt_int16)==2 ? 1 : -1];
382 #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func)
388 #define STBTT_ifloor(x) ((int) floor(x))
389 #define STBTT_iceil(x) ((int) ceil(x))
394 #define STBTT_sqrt(x) sqrt(x)
400 #define STBTT_malloc(x,u) ((void)(u),malloc(x))
401 #define STBTT_free(x,u) ((void)(u),free(x))
406 #define STBTT_assert(x) assert(x)
411 #define STBTT_strlen(x) strlen(x)
416 #define STBTT_memcpy memcpy
417 #define STBTT_memset memset
428 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
429 #define __STB_INCLUDE_STB_TRUETYPE_H__
444 unsigned short x0,y0,x1,y1;
445 float xoff,yoff,xadvance;
450 unsigned char *pixels,
int pw,
int ph,
451 int first_char,
int num_chars,
466 float *xpos,
float *ypos,
468 int opengl_fillrule);
490 unsigned short x0,y0,x1,y1;
491 float xoff,yoff,xadvance;
511 #define STBTT_POINT_SIZE(x) (-(x))
513 extern int stbtt_PackFontRange(stbtt_pack_context *spc,
unsigned char *fontdata,
int font_index,
float font_size,
514 int first_unicode_char_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range);
531 int first_unicode_char_in_range;
532 int num_chars_in_range;
556 float *xpos,
float *ypos,
558 int align_to_integer);
562 struct stbtt_pack_context {
594 unsigned char *
data;
675 #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
683 #ifndef stbtt_vertex // you can predefine this to use different values
685 #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
689 unsigned char type,padding;
767 unsigned char *pixels;
770 extern 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);
799 #define STBTT_MACSTYLE_DONTCARE 0
800 #define STBTT_MACSTYLE_BOLD 1
801 #define STBTT_MACSTYLE_ITALIC 2
802 #define STBTT_MACSTYLE_UNDERSCORE 4
803 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
870 #endif // __STB_INCLUDE_STB_TRUETYPE_H__
879 #ifdef STB_TRUETYPE_IMPLEMENTATION
881 #ifndef STBTT_MAX_OVERSAMPLE
882 #define STBTT_MAX_OVERSAMPLE 8
885 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
895 #define ttBYTE(p) (* (stbtt_uint8 *) (p))
896 #define ttCHAR(p) (* (stbtt_int8 *) (p))
897 #define ttFixed(p) ttLONG(p)
899 #if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE)
901 #define ttUSHORT(p) (* (stbtt_uint16 *) (p))
902 #define ttSHORT(p) (* (stbtt_int16 *) (p))
903 #define ttULONG(p) (* (stbtt_uint32 *) (p))
904 #define ttLONG(p) (* (stbtt_int32 *) (p))
908 stbtt_uint16 ttUSHORT(
const stbtt_uint8 *p) {
return p[0]*256 + p[1]; }
909 stbtt_int16 ttSHORT(
const stbtt_uint8 *p) {
return p[0]*256 + p[1]; }
910 stbtt_uint32 ttULONG(
const stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
911 stbtt_int32 ttLONG(
const stbtt_uint8 *p) {
return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
915 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
916 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
918 static int stbtt__isfont(
const stbtt_uint8 *font)
921 if (stbtt_tag4(font,
'1',0,0,0))
return 1;
922 if (stbtt_tag(font,
"typ1"))
return 1;
923 if (stbtt_tag(font,
"OTTO"))
return 1;
924 if (stbtt_tag4(font, 0,1,0,0))
return 1;
929 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart,
const char *tag)
931 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
932 stbtt_uint32 tabledir = fontstart + 12;
934 for (i=0; i < num_tables; ++i) {
935 stbtt_uint32 loc = tabledir + 16*i;
936 if (stbtt_tag(data+loc+0, tag))
937 return ttULONG(data+loc+8);
945 if (stbtt__isfont(font_collection))
946 return index == 0 ? 0 : -1;
949 if (stbtt_tag(font_collection,
"ttcf")) {
951 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
952 stbtt_int32 n = ttLONG(font_collection+8);
955 return ttULONG(font_collection+12+index*14);
963 stbtt_uint8 *data = (stbtt_uint8 *) data2;
964 stbtt_uint32 cmap, t;
965 stbtt_int32 i,numTables;
970 cmap = stbtt__find_table(data, fontstart,
"cmap");
971 info->
loca = stbtt__find_table(data, fontstart,
"loca");
972 info->
head = stbtt__find_table(data, fontstart,
"head");
973 info->
glyf = stbtt__find_table(data, fontstart,
"glyf");
974 info->
hhea = stbtt__find_table(data, fontstart,
"hhea");
975 info->
hmtx = stbtt__find_table(data, fontstart,
"hmtx");
976 info->
kern = stbtt__find_table(data, fontstart,
"kern");
980 t = stbtt__find_table(data, fontstart,
"maxp");
989 numTables = ttUSHORT(data + cmap + 2);
991 for (i=0; i < numTables; ++i) {
992 stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
994 switch(ttUSHORT(data+encoding_record)) {
996 switch (ttUSHORT(data+encoding_record+2)) {
1000 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1007 info->
index_map = cmap + ttULONG(data+encoding_record+4);
1020 stbtt_uint8 *data = info->
data;
1021 stbtt_uint32 index_map = info->
index_map;
1023 stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1025 stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1026 if (unicode_codepoint < bytes-6)
1027 return ttBYTE(data + index_map + 6 + unicode_codepoint);
1029 }
else if (format == 6) {
1030 stbtt_uint32 first = ttUSHORT(data + index_map + 6);
1031 stbtt_uint32 count = ttUSHORT(data + index_map + 8);
1032 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
1033 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
1035 }
else if (format == 2) {
1038 }
else if (format == 4) {
1039 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
1040 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
1041 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
1042 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
1043 stbtt_uint16 item, offset, start, end;
1046 stbtt_uint32 endCount = index_map + 14;
1047 stbtt_uint32 search = endCount;
1049 if (unicode_codepoint > 0xffff)
1054 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
1055 search += rangeShift*2;
1059 while (entrySelector) {
1061 start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2);
1062 end = ttUSHORT(data + search + searchRange*2);
1063 if (unicode_codepoint > end)
1064 search += searchRange*2;
1069 item = (stbtt_uint16) ((search - endCount) >> 1);
1071 STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1072 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1073 end = ttUSHORT(data + index_map + 14 + 2 + 2*item);
1074 if (unicode_codepoint < start)
1077 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
1079 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
1081 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
1082 }
else if (format == 12 || format == 13) {
1083 stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1084 stbtt_int32 low,high;
1085 low = 0; high = (stbtt_int32)ngroups;
1087 while (low < high) {
1088 stbtt_int32 mid = low + ((high-low) >> 1);
1089 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
1090 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
1091 if ((stbtt_uint32) unicode_codepoint < start_char)
1093 else if ((stbtt_uint32) unicode_codepoint > end_char)
1096 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
1098 return start_glyph + unicode_codepoint-start_char;
1115 static void stbtt_setvertex(
stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
1118 v->
x = (stbtt_int16) x;
1119 v->
y = (stbtt_int16) y;
1120 v->
cx = (stbtt_int16) cx;
1121 v->
cy = (stbtt_int16) cy;
1124 static int stbtt__GetGlyfOffset(
const stbtt_fontinfo *info,
int glyph_index)
1128 if (glyph_index >= info->
numGlyphs)
return -1;
1132 g1 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2) * 2;
1133 g2 = info->
glyf + ttUSHORT(info->
data + info->
loca + glyph_index * 2 + 2) * 2;
1135 g1 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4);
1136 g2 = info->
glyf + ttULONG (info->
data + info->
loca + glyph_index * 4 + 4);
1139 return g1==g2 ? -1 : g1;
1144 int g = stbtt__GetGlyfOffset(info, glyph_index);
1145 if (g < 0)
return 0;
1147 if (x0) *x0 = ttSHORT(info->
data + g + 2);
1148 if (y0) *y0 = ttSHORT(info->
data + g + 4);
1149 if (x1) *x1 = ttSHORT(info->
data + g + 6);
1150 if (y1) *y1 = ttSHORT(info->
data + g + 8);
1161 stbtt_int16 numberOfContours;
1162 int g = stbtt__GetGlyfOffset(info, glyph_index);
1163 if (g < 0)
return 1;
1164 numberOfContours = ttSHORT(info->
data + g);
1165 return numberOfContours == 0;
1168 static int stbtt__close_shape(
stbtt_vertex *vertices,
int num_vertices,
int was_off,
int start_off,
1169 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
1173 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
1174 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, sx,sy,scx,scy);
1177 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve,sx,sy,cx,cy);
1179 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline,sx,sy,0,0);
1181 return num_vertices;
1186 stbtt_int16 numberOfContours;
1187 stbtt_uint8 *endPtsOfContours;
1188 stbtt_uint8 *data = info->
data;
1191 int g = stbtt__GetGlyfOffset(info, glyph_index);
1195 if (g < 0)
return 0;
1197 numberOfContours = ttSHORT(data + g);
1199 if (numberOfContours > 0) {
1200 stbtt_uint8 flags=0,flagcount;
1201 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
1202 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
1203 stbtt_uint8 *points;
1204 endPtsOfContours = (data + g + 10);
1205 ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
1206 points = data + g + 10 + numberOfContours * 2 + 2 + ins;
1208 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
1210 m = n + 2*numberOfContours;
1226 for (i=0; i < n; ++i) {
1227 if (flagcount == 0) {
1230 flagcount = *points++;
1233 vertices[off+i].
type = flags;
1238 for (i=0; i < n; ++i) {
1239 flags = vertices[off+i].
type;
1241 stbtt_int16 dx = *points++;
1242 x += (flags & 16) ? dx : -dx;
1244 if (!(flags & 16)) {
1245 x = x + (stbtt_int16) (points[0]*256 + points[1]);
1249 vertices[off+i].
x = (stbtt_int16) x;
1254 for (i=0; i < n; ++i) {
1255 flags = vertices[off+i].
type;
1257 stbtt_int16 dy = *points++;
1258 y += (flags & 32) ? dy : -dy;
1260 if (!(flags & 32)) {
1261 y = y + (stbtt_int16) (points[0]*256 + points[1]);
1265 vertices[off+i].
y = (stbtt_int16) y;
1270 sx = sy = cx = cy = scx = scy = 0;
1271 for (i=0; i < n; ++i) {
1272 flags = vertices[off+i].
type;
1273 x = (stbtt_int16) vertices[off+i].x;
1274 y = (stbtt_int16) vertices[off+i].y;
1276 if (next_move == i) {
1278 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1281 start_off = !(flags & 1);
1287 if (!(vertices[off+i+1].type & 1)) {
1289 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
1290 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
1293 sx = (stbtt_int32) vertices[off+i+1].x;
1294 sy = (stbtt_int32) vertices[off+i+1].y;
1301 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vmove,sx,sy,0,0);
1303 next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
1308 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
1314 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vcurve, x,y, cx, cy);
1316 stbtt_setvertex(&vertices[num_vertices++],
STBTT_vline, x,y,0,0);
1321 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
1322 }
else if (numberOfContours == -1) {
1325 stbtt_uint8 *comp = data + g + 10;
1329 stbtt_uint16 flags, gidx;
1330 int comp_num_verts = 0, i;
1332 float mtx[6] = {1,0,0,1,0,0}, m, n;
1334 flags = ttSHORT(comp); comp+=2;
1335 gidx = ttSHORT(comp); comp+=2;
1339 mtx[4] = ttSHORT(comp); comp+=2;
1340 mtx[5] = ttSHORT(comp); comp+=2;
1342 mtx[4] = ttCHAR(comp); comp+=1;
1343 mtx[5] = ttCHAR(comp); comp+=1;
1350 if (flags & (1<<3)) {
1351 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1352 mtx[1] = mtx[2] = 0;
1353 }
else if (flags & (1<<6)) {
1354 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1355 mtx[1] = mtx[2] = 0;
1356 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1357 }
else if (flags & (1<<7)) {
1358 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
1359 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
1360 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
1361 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
1365 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
1366 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
1370 if (comp_num_verts > 0) {
1372 for (i = 0; i < comp_num_verts; ++i) {
1389 if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*
sizeof(
stbtt_vertex));
1390 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*
sizeof(
stbtt_vertex));
1394 num_vertices += comp_num_verts;
1397 more = flags & (1<<5);
1399 }
else if (numberOfContours < 0) {
1406 *pvertices = vertices;
1407 return num_vertices;
1412 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->
data+info->
hhea + 34);
1413 if (glyph_index < numOfLongHorMetrics) {
1414 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*glyph_index);
1415 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*glyph_index + 2);
1417 if (advanceWidth) *advanceWidth = ttSHORT(info->
data + info->
hmtx + 4*(numOfLongHorMetrics-1));
1418 if (leftSideBearing) *leftSideBearing = ttSHORT(info->
data + info->
hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
1424 stbtt_uint8 *data = info->
data + info->
kern;
1425 stbtt_uint32 needle, straw;
1431 if (ttUSHORT(data+2) < 1)
1433 if (ttUSHORT(data+8) != 1)
1437 r = ttUSHORT(data+10) - 1;
1438 needle = glyph1 << 16 | glyph2;
1441 straw = ttULONG(data+18+(m*6));
1444 else if (needle > straw)
1447 return ttSHORT(data+22+(m*6));
1466 if (ascent ) *ascent = ttSHORT(info->
data+info->
hhea + 4);
1467 if (descent) *descent = ttSHORT(info->
data+info->
hhea + 6);
1468 if (lineGap) *lineGap = ttSHORT(info->
data+info->
hhea + 8);
1473 *x0 = ttSHORT(info->
data + info->
head + 36);
1474 *y0 = ttSHORT(info->
data + info->
head + 38);
1475 *x1 = ttSHORT(info->
data + info->
head + 40);
1476 *y1 = ttSHORT(info->
data + info->
head + 42);
1481 int fheight = ttSHORT(info->
data + info->
hhea + 4) - ttSHORT(info->
data + info->
hhea + 6);
1482 return (
float) height / fheight;
1487 int unitsPerEm = ttUSHORT(info->
data + info->
head + 18);
1488 return pixels / unitsPerEm;
1512 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
1513 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
1514 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
1515 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
1526 stbtt_GetGlyphBitmapBoxSubpixel(font,
stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
1534 typedef struct stbtt__edge {
1539 typedef struct stbtt__active_edge
1543 struct stbtt__active_edge *next;
1545 } stbtt__active_edge;
1548 #define FIX (1 << FIXSHIFT)
1549 #define FIXMASK (FIX-1)
1551 static stbtt__active_edge *new_active(stbtt__edge *e,
int off_x,
float start_point,
void *userdata)
1553 stbtt__active_edge *z = (stbtt__active_edge *)
STBTT_malloc(
sizeof(*z), userdata);
1554 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
1559 z->dx = -STBTT_ifloor(FIX * -dxdy);
1561 z->dx = STBTT_ifloor(FIX * dxdy);
1562 z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0)));
1563 z->x -= off_x * FIX;
1566 z->valid = e->invert ? 1 : -1;
1573 static void stbtt__fill_active_edges(
unsigned char *scanline,
int len, stbtt__active_edge *e,
int max_weight)
1581 x0 = e->x; w += e->valid;
1583 int x1 = e->x; w += e->valid;
1586 int i = x0 >> FIXSHIFT;
1587 int j = x1 >> FIXSHIFT;
1589 if (i < len && j >= 0) {
1592 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT);
1595 scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT);
1600 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT);
1604 for (++i; i < j; ++i)
1605 scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
1615 static void stbtt__rasterize_sorted_edges(
stbtt__bitmap *result, stbtt__edge *e,
int n,
int vsubsample,
int off_x,
int off_y,
void *userdata)
1617 stbtt__active_edge *active = NULL;
1619 int max_weight = (255 / vsubsample);
1621 unsigned char scanline_data[512], *scanline;
1623 if (result->
w > 512)
1624 scanline = (
unsigned char *)
STBTT_malloc(result->
w, userdata);
1626 scanline = scanline_data;
1628 y = off_y * vsubsample;
1629 e[n].y0 = (off_y + result->
h) * (
float) vsubsample + 1;
1631 while (j < result->h) {
1632 STBTT_memset(scanline, 0, result->
w);
1633 for (s=0; s < vsubsample; ++s) {
1635 float scan_y = y + 0.5f;
1636 stbtt__active_edge **step = &active;
1641 stbtt__active_edge * z = *step;
1642 if (z->ey <= scan_y) {
1649 step = &((*step)->next);
1657 while (*step && (*step)->next) {
1658 if ((*step)->x > (*step)->next->x) {
1659 stbtt__active_edge *t = *step;
1660 stbtt__active_edge *q = t->next;
1667 step = &(*step)->next;
1669 if (!changed)
break;
1673 while (e->y0 <= scan_y) {
1674 if (e->y1 > scan_y) {
1675 stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata);
1679 else if (z->x < active->x) {
1685 stbtt__active_edge *p = active;
1686 while (p->next && p->next->x < z->x)
1698 stbtt__fill_active_edges(scanline, result->
w, active, max_weight);
1702 STBTT_memcpy(result->
pixels + j * result->
stride, scanline, result->
w);
1707 stbtt__active_edge *z = active;
1708 active = active->next;
1712 if (scanline != scanline_data)
1716 static int stbtt__edge_compare(
const void *p,
const void *q)
1718 stbtt__edge *a = (stbtt__edge *) p;
1719 stbtt__edge *b = (stbtt__edge *) q;
1721 if (a->y0 < b->y0)
return -1;
1722 if (a->y0 > b->y0)
return 1;
1731 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)
1733 float y_scale_inv = invert ? -scale_y : scale_y;
1736 int vsubsample = result->
h < 8 ? 15 : 5;
1741 for (i=0; i < windings; ++i)
1744 e = (stbtt__edge *)
STBTT_malloc(
sizeof(*e) * (n+1), userdata);
1749 for (i=0; i < windings; ++i) {
1750 stbtt__point *p = pts + m;
1753 for (k=0; k < wcount[i]; j=k++) {
1756 if (p[j].y == p[k].y)
1760 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
1764 e[n].x0 = p[a].x * scale_x + shift_x;
1765 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
1766 e[n].x1 = p[b].x * scale_x + shift_x;
1767 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
1773 STBTT_sort(e, n,
sizeof(e[0]), stbtt__edge_compare);
1776 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
1781 static void stbtt__add_point(stbtt__point *points,
int n,
float x,
float y)
1783 if (!points)
return;
1789 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)
1792 float mx = (x0 + 2*x1 + x2)/4;
1793 float my = (y0 + 2*y1 + y2)/4;
1795 float dx = (x0+x2)/2 - mx;
1796 float dy = (y0+y2)/2 - my;
1799 if (dx*dx+dy*dy > objspace_flatness_squared) {
1800 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
1801 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
1803 stbtt__add_point(points, *num_points,x2,y2);
1804 *num_points = *num_points+1;
1810 stbtt__point *stbtt_FlattenCurves(
stbtt_vertex *vertices,
int num_verts,
float objspace_flatness,
int **contour_lengths,
int *num_contours,
void *userdata)
1812 stbtt__point *points=0;
1815 float objspace_flatness_squared = objspace_flatness * objspace_flatness;
1816 int i,n=0,start=0, pass;
1819 for (i=0; i < num_verts; ++i)
1824 if (n == 0)
return 0;
1826 *contour_lengths = (
int *)
STBTT_malloc(
sizeof(**contour_lengths) * n, userdata);
1828 if (*contour_lengths == 0) {
1834 for (pass=0; pass < 2; ++pass) {
1837 points = (stbtt__point *)
STBTT_malloc(num_points *
sizeof(points[0]), userdata);
1838 if (points == NULL)
goto error;
1842 for (i=0; i < num_verts; ++i) {
1843 switch (vertices[i].type) {
1847 (*contour_lengths)[n] = num_points - start;
1851 x = vertices[i].
x, y = vertices[i].
y;
1852 stbtt__add_point(points, num_points++, x,y);
1855 x = vertices[i].
x, y = vertices[i].
y;
1856 stbtt__add_point(points, num_points++, x, y);
1859 stbtt__tesselate_curve(points, &num_points, x,y,
1860 vertices[i].cx, vertices[i].cy,
1861 vertices[i].x, vertices[i].y,
1862 objspace_flatness_squared, 0);
1863 x = vertices[i].
x, y = vertices[i].
y;
1867 (*contour_lengths)[n] = num_points - start;
1874 *contour_lengths = 0;
1879 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)
1881 float scale = scale_x > scale_y ? scale_y : scale_x;
1882 int winding_count, *winding_lengths;
1883 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
1885 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
1898 int ix0,iy0,ix1,iy1;
1903 if (scale_x == 0) scale_x = scale_y;
1905 if (scale_x == 0)
return NULL;
1912 gbm.
w = (ix1 - ix0);
1913 gbm.
h = (iy1 - iy0);
1916 if (width ) *width = gbm.
w;
1917 if (height) *height = gbm.
h;
1918 if (xoff ) *xoff = ix0;
1919 if (yoff ) *yoff = iy0;
1921 if (gbm.
w && gbm.
h) {
1926 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->
userdata);
1952 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->
userdata);
1964 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y,
stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
1969 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y,
stbtt_FindGlyphIndex(info,codepoint));
1990 unsigned char *pixels,
int pw,
int ph,
1991 int first_char,
int num_chars,
1995 int x,y,bottom_y, i;
1999 STBTT_memset(pixels, 0, pw*ph);
2005 for (i=0; i < num_chars; ++i) {
2006 int advance, lsb, x0,y0,x1,y1,gw,gh;
2012 if (x + gw + 1 >= pw)
2013 y = bottom_y, x = 1;
2014 if (y + gh + 1 >= ph)
2019 chardata[i].
x0 = (stbtt_int16) x;
2020 chardata[i].
y0 = (stbtt_int16) y;
2021 chardata[i].
x1 = (stbtt_int16) (x + gw);
2022 chardata[i].
y1 = (stbtt_int16) (y + gh);
2023 chardata[i].
xadvance = scale * advance;
2024 chardata[i].
xoff = (float) x0;
2025 chardata[i].
yoff = (float) y0;
2027 if (y+gh+1 > bottom_y)
2035 float d3d_bias = opengl_fillrule ? 0 : -0.5f;
2036 float ipw = 1.0f / pw, iph = 1.0f / ph;
2038 int round_x = STBTT_ifloor((*xpos + b->
xoff) + 0.5);
2039 int round_y = STBTT_ifloor((*ypos + b->
yoff) + 0.5);
2041 q->
x0 = round_x + d3d_bias;
2042 q->
y0 = round_y + d3d_bias;
2043 q->
x1 = round_x + b->
x1 - b->
x0 + d3d_bias;
2044 q->
y1 = round_y + b->
y1 - b->
y0 + d3d_bias;
2046 q->
s0 = b->
x0 * ipw;
2047 q->
t0 = b->
y0 * iph;
2048 q->
s1 = b->
x1 * ipw;
2049 q->
t1 = b->
y1 * iph;
2059 #ifndef STB_RECT_PACK_VERSION
2061 #define STBTT__NOTUSED(v) (void)(v)
2063 #define STBTT__NOTUSED(v) (void)sizeof(v)
2093 int id,w,h,was_packed;
2103 STBTT__NOTUSED(nodes);
2104 STBTT__NOTUSED(num_nodes);
2110 for (i=0; i < num_rects; ++i) {
2111 if (con->x + rects[i].
w > con->
width) {
2113 con->y = con->bottom_y;
2115 if (con->y + rects[i].
h > con->
height)
2117 rects[i].
x = con->x;
2118 rects[i].
y = con->y;
2120 con->x += rects[i].
w;
2121 if (con->y + rects[i].
h > con->bottom_y)
2122 con->bottom_y = con->y + rects[i].
h;
2124 for ( ; i < num_rects; ++i)
2125 rects[i].was_packed = 0;
2139 int num_nodes = pw - padding;
2142 if (context == NULL || nodes == NULL) {
2143 if (context != NULL)
STBTT_free(context, alloc_context);
2144 if (nodes != NULL)
STBTT_free(nodes , alloc_context);
2161 STBTT_memset(pixels, 0, pw*ph);
2176 if (h_oversample <= STBTT_MAX_OVERSAMPLE)
2178 if (v_oversample <= STBTT_MAX_OVERSAMPLE)
2182 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
2184 static void stbtt__h_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
2186 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2187 int safe_w = w - kernel_width;
2189 for (j=0; j < h; ++j) {
2192 memset(buffer, 0, kernel_width);
2197 switch (kernel_width) {
2199 for (i=0; i <= safe_w; ++i) {
2200 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2201 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2202 pixels[i] = (
unsigned char) (total / 2);
2206 for (i=0; i <= safe_w; ++i) {
2207 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2208 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2209 pixels[i] = (
unsigned char) (total / 3);
2213 for (i=0; i <= safe_w; ++i) {
2214 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2215 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2216 pixels[i] = (
unsigned char) (total / 4);
2220 for (i=0; i <= safe_w; ++i) {
2221 total += pixels[i] - buffer[i & STBTT__OVER_MASK];
2222 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
2223 pixels[i] = (
unsigned char) (total / kernel_width);
2228 for (; i < w; ++i) {
2230 total -= buffer[i & STBTT__OVER_MASK];
2231 pixels[i] = (
unsigned char) (total / kernel_width);
2234 pixels += stride_in_bytes;
2238 static void stbtt__v_prefilter(
unsigned char *pixels,
int w,
int h,
int stride_in_bytes,
unsigned int kernel_width)
2240 unsigned char buffer[STBTT_MAX_OVERSAMPLE];
2241 int safe_h = h - kernel_width;
2243 for (j=0; j < w; ++j) {
2246 memset(buffer, 0, kernel_width);
2251 switch (kernel_width) {
2253 for (i=0; i <= safe_h; ++i) {
2254 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2255 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2256 pixels[i*stride_in_bytes] = (
unsigned char) (total / 2);
2260 for (i=0; i <= safe_h; ++i) {
2261 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2262 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2263 pixels[i*stride_in_bytes] = (
unsigned char) (total / 3);
2267 for (i=0; i <= safe_h; ++i) {
2268 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2269 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2270 pixels[i*stride_in_bytes] = (
unsigned char) (total / 4);
2274 for (i=0; i <= safe_h; ++i) {
2275 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
2276 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
2277 pixels[i*stride_in_bytes] = (
unsigned char) (total / kernel_width);
2282 for (; i < h; ++i) {
2284 total -= buffer[i & STBTT__OVER_MASK];
2285 pixels[i*stride_in_bytes] = (
unsigned char) (total / kernel_width);
2292 static float stbtt__oversample_shift(
int oversample)
2301 return (
float)-(oversample - 1) / (2.0f * (
float)oversample);
2309 float sub_x = stbtt__oversample_shift(spc->
h_oversample);
2310 float sub_y = stbtt__oversample_shift(spc->
v_oversample);
2311 int i,j,k,n, return_value = 1;
2316 for (i=0; i < num_ranges; ++i)
2318 ranges[i].chardata_for_range[j].x0 =
2319 ranges[i].chardata_for_range[j].y0 =
2320 ranges[i].chardata_for_range[j].x1 =
2321 ranges[i].chardata_for_range[j].y1 = 0;
2324 for (i=0; i < num_ranges; ++i)
2325 n += ranges[i].num_chars_in_range;
2333 for (i=0; i < num_ranges; ++i) {
2352 for (i=0; i < num_ranges; ++i) {
2359 int advance, lsb, x0,y0,x1,y1;
2393 bc->
x0 = (stbtt_int16) r->
x;
2394 bc->
y0 = (stbtt_int16) r->
y;
2395 bc->
x1 = (stbtt_int16) (r->
x + r->
w);
2396 bc->
y1 = (stbtt_int16) (r->
y + r->
h);
2398 bc->
xoff = (float) x0 * recip_h + sub_x;
2399 bc->
yoff = (float) y0 * recip_v + sub_y;
2400 bc->
xoff2 = (x0 + r->
w) * recip_h + sub_x;
2401 bc->
yoff2 = (y0 + r->
h) * recip_v + sub_y;
2410 return return_value;
2414 int first_unicode_char_in_range,
int num_chars_in_range,
stbtt_packedchar *chardata_for_range)
2426 float ipw = 1.0f / pw, iph = 1.0f / ph;
2429 if (align_to_integer) {
2430 float x = (float) STBTT_ifloor((*xpos + b->
xoff) + 0.5);
2431 float y = (float) STBTT_ifloor((*ypos + b->
yoff) + 0.5);
2443 q->
s0 = b->
x0 * ipw;
2444 q->
t0 = b->
y0 * iph;
2445 q->
s1 = b->
x1 * ipw;
2446 q->
t1 = b->
y1 * iph;
2458 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(
const stbtt_uint8 *s1, stbtt_int32 len1,
const stbtt_uint8 *s2, stbtt_int32 len2)
2464 stbtt_uint16 ch = s2[0]*256 + s2[1];
2466 if (i >= len1)
return -1;
2467 if (s1[i++] != ch)
return -1;
2468 }
else if (ch < 0x800) {
2469 if (i+1 >= len1)
return -1;
2470 if (s1[i++] != 0xc0 + (ch >> 6))
return -1;
2471 if (s1[i++] != 0x80 + (ch & 0x3f))
return -1;
2472 }
else if (ch >= 0xd800 && ch < 0xdc00) {
2474 stbtt_uint16 ch2 = s2[2]*256 + s2[3];
2475 if (i+3 >= len1)
return -1;
2476 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
2477 if (s1[i++] != 0xf0 + (c >> 18))
return -1;
2478 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f))
return -1;
2479 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f))
return -1;
2480 if (s1[i++] != 0x80 + ((c ) & 0x3f))
return -1;
2483 }
else if (ch >= 0xdc00 && ch < 0xe000) {
2486 if (i+2 >= len1)
return -1;
2487 if (s1[i++] != 0xe0 + (ch >> 12))
return -1;
2488 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f))
return -1;
2489 if (s1[i++] != 0x80 + ((ch ) & 0x3f))
return -1;
2499 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((
const stbtt_uint8*) s1, len1, (
const stbtt_uint8*) s2, len2);
2506 stbtt_int32 i,count,stringOffset;
2507 stbtt_uint8 *fc = font->
data;
2509 stbtt_uint32 nm = stbtt__find_table(fc, offset,
"name");
2510 if (!nm)
return NULL;
2512 count = ttUSHORT(fc+nm+2);
2513 stringOffset = nm + ttUSHORT(fc+nm+4);
2514 for (i=0; i < count; ++i) {
2515 stbtt_uint32 loc = nm + 6 + 12 * i;
2516 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
2517 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
2518 *length = ttUSHORT(fc+loc+8);
2519 return (
const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
2525 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
2528 stbtt_int32 count = ttUSHORT(fc+nm+2);
2529 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
2531 for (i=0; i < count; ++i) {
2532 stbtt_uint32 loc = nm + 6 + 12 * i;
2533 stbtt_int32
id = ttUSHORT(fc+loc+6);
2534 if (
id == target_id) {
2536 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
2539 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
2540 stbtt_int32 slen = ttUSHORT(fc+loc+8);
2541 stbtt_int32 off = ttUSHORT(fc+loc+10);
2544 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
2545 if (matchlen >= 0) {
2547 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) {
2548 slen = ttUSHORT(fc+loc+12+8);
2549 off = ttUSHORT(fc+loc+12+10);
2551 if (matchlen == nlen)
2553 }
else if (matchlen < nlen && name[matchlen] ==
' ') {
2560 if (matchlen == nlen)
2572 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
2574 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((
char *) name);
2576 if (!stbtt__isfont(fc+offset))
return 0;
2580 hd = stbtt__find_table(fc, offset,
"head");
2581 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7))
return 0;
2584 nm = stbtt__find_table(fc, offset,
"name");
2589 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))
return 1;
2590 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1))
return 1;
2591 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
2593 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))
return 1;
2594 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2))
return 1;
2595 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1))
return 1;
2601 int stbtt_FindMatchingFont(
const unsigned char *font_collection,
const char *name_utf8, stbtt_int32 flags)
2606 if (off < 0)
return off;
2607 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
2612 #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_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)
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)
#define stbtt_vertex_type
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 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)