History

update stb header and remove c2g crappy search

Sigrid Solveig Haflínudóttir committed 5 years ago

Commit e771f321 parent b43d58c3 files · +366 −408Browse files

Unified · Split

3 files
  1. pt.c +14 −12
  2. pt_private.h +0 −2
  3. stb_truetype.h +352 −394
pt.c+14−12
@@ -67,6 +67,18 @@ utf16to8(uchar *o, int osz, const uchar *s, int sz) · 66 unmodified lines
6767 }
6868
6969 #define STB_TRUETYPE_IMPLEMENTATION
70+static void *
71+STBTT_malloc(int x, void *)
72+{
73+ return malloc(x);
74+}
75+static void
76+STBTT_free(void *p, void *)
77+{
78+ free(p);
79+}
80+#define STBTT_malloc STBTT_malloc
81+#define STBTT_free STBTT_free
7082 #define STBTT_ifloor(x) ((int)floor(x))
7183 #define STBTT_iceil(x) ((int)ceil(x))
7284 #define STBTT_sqrt(x) sqrt(x)
@@ -75,15 +87,13 @@ utf16to8(uchar *o, int osz, const uchar *s, int sz) · 2 unmodified lines
7587 #define STBTT_cos(x) cos(x)
7688 #define STBTT_acos(x) acos(x)
7789 #define STBTT_fabs(x) fabs(x)
78−#define STBTT_malloc(x,u) ((void)(u),malloc(x))
79−#define STBTT_free(x,u) ((void)(u),free(x))
8090 #define STBTT_assert(x) assert(x)
8191 #define STBTT_strlen(x) strlen(x)
8292 #define STBTT_memcpy memmove
8393 #define STBTT_memset memset
8494 typedef usize size_t;
8595 #define NULL nil
86−#define STBTT_RASTERIZER_VERSION 1 /* that one is definitely FASTER on amd64 */
96+#define STBTT_RASTERIZER_VERSION 2 /* that one is definitely FASTER on amd64 */
8797 #include "pt_private.h"
8898
8999 Sfont *
@@ -95,7 +105,6 @@ pt_font(uchar *data, float height) · 5 unmodified lines
95105 if(stbtt_InitFont(&f->fi, data, stbtt_GetFontOffsetForIndex(data, 0)) == 0)
96106 goto err;
97107
98− f->c2g = stbtt_Code2Glyph(&f->fi);
99108 f->scale = stbtt_ScaleForPixelHeight(&f->fi, height);
100109 f->height = height;
101110 stbtt_GetFontVMetrics(&f->fi, &f->asc, &f->desc, &f->linegap);
@@ -127,7 +136,6 @@ pt_freefont(Sfont *f) · 25 unmodified lines
127136 {
128137 if(f == nil)
129138 return;
130− free(f->c2g);
131139 freememimage(f->g);
132140 freememimage(f->b);
133141 free(f);
@@ -156,13 +164,7 @@ bsearch(u32int c, u32int *t, int n) · 22 unmodified lines
156164 static int
157165 code2glyph(Sfont *f, u32int c)
158166 {
159− u32int *r;
160−
161− if(f->c2g == nil)
162− return stbtt_FindGlyphIndex(&f->fi, c);
163− if((r = bsearch(c, f->c2g->code, f->c2g->num)) != nil)
164− return f->c2g->glyph[r - f->c2g->code];
165− return 0;
167+ return stbtt_FindGlyphIndex(&f->fi, c);
166168 }
167169
168170 Rectangle
pt_private.h+0−2
@@ -4,8 +4,6 @@ struct Sfont { · 3 unmodified lines
44 Memimage *g;
55 Memimage *b;
66
7− stbtt_code2glyph *c2g;
8−
97 Rectangle bb;
108 float scale;
119 float height;
stb_truetype.h+352−394
@@ -1,5 +1,5 @@
1−// stb_truetype.h - v1.24 - public domain
2−// authored from 2009-2020 by Sean Barrett / RAD Game Tools
1+// stb_truetype.h - v1.26 - public domain
2+// authored from 2009-2021 by Sean Barrett / RAD Game Tools
33 //
44 // =======================================================================
55 //
@@ -53,11 +53,13 @@ · 47 unmodified lines
5353 // Johan Duparc Thomas Fields
5454 // Hou Qiming Derek Vinyard
5555 // Rob Loach Cort Stratton
56−// Kenney Phillis Jr. Brian Costabile
57−// Ken Voskuil (kaesve)
56+// Kenney Phillis Jr. Brian Costabile
57+// Ken Voskuil (kaesve)
5858 //
5959 // VERSION HISTORY
6060 //
61+// 1.26 (2021-08-28) fix broken rasterizer
62+// 1.25 (2021-07-11) many fixes
6163 // 1.24 (2020-02-05) fix warning
6264 // 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
6365 // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
@@ -270,8 +272,8 @@ · 206 unmodified lines
270272 //// SAMPLE PROGRAMS
271273 ////
272274 //
273−// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
274−//
275+// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
276+// See "tests/truetype_demo_win32.c" for a complete version.
275277 #if 0
276278 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
277279 #include "stb_truetype.h"
@@ -297,6 +299,8 @@ void my_stbtt_initfont(void) · 19 unmodified lines
297299 void my_stbtt_print(float x, float y, char *text)
298300 {
299301 // assume orthographic projection with units = screen pixels, origin at top left
302+ glEnable(GL_BLEND);
303+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
300304 glEnable(GL_TEXTURE_2D);
301305 glBindTexture(GL_TEXTURE_2D, ftex);
302306 glBegin(GL_QUADS);
@@ -304,10 +308,10 @@ void my_stbtt_print(float x, float y, char *text) · 1 unmodified line
304308 if (*text >= 32 && *text < 128) {
305309 stbtt_aligned_quad q;
306310 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
307− glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
308− glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
309− glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
310− glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
311+ glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
312+ glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
313+ glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
314+ glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
311315 }
312316 ++text;
313317 }
@@ -717,10 +721,6 @@ struct stbtt_fontinfo · 403 unmodified lines
717721 int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
718722 int index_map; // a cmap mapping for our chosen character encoding
719723 int indexToLocFormat; // format needed to map from glyph index to glyph
720− int underlinePosition;
721− int underlineThickness;
722− char family[128];
723− char subfamily[128];
724724
725725 stbtt__buf cff; // cff font data
726726 stbtt__buf charstrings; // the charstring index
@@ -857,6 +857,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s · 130 unmodified lines
857857 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
858858 // frees the data allocated above
859859
860+STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
860861 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
861862 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
862863 // fills svg with the character's SVG data.
@@ -1382,9 +1383,7 @@ static int stbtt__get_svg(stbtt_fontinfo *info) · 519 unmodified lines
13821383 static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
13831384 {
13841385 stbtt_uint32 cmap, t;
1385− stbtt_int32 i, numTables;
1386−
1387− memset(info, 0, sizeof(*info));
1386+ stbtt_int32 i,numTables;
13881387
13891388 info->data = data;
13901389 info->fontstart = fontstart;
@@ -1462,43 +1461,6 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in · 71 unmodified lines
14621461
14631462 info->svg = -1;
14641463
1465− t = stbtt__find_table(data, fontstart, "post");
1466− if (t) {
1467− info->underlinePosition = ttSHORT(data+t+8);
1468− info->underlineThickness = ttUSHORT(data+t+10);
1469− }
1470−
1471− t = stbtt__find_table(data, fontstart, "name");
1472− if (t) {
1473− stbtt_int32 i, platform, name, count, stringOffset, length;
1474− stbtt_uint8 *fc = data;
1475− stbtt_uint32 offset = fontstart;
1476− stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
1477− char *o, tmp[256];
1478−
1479− count = ttUSHORT(fc+nm+2);
1480− stringOffset = nm + ttUSHORT(fc+nm+4);
1481− for (i=0; i < count; ++i) {
1482− stbtt_uint32 loc = nm + 6 + 12 * i;
1483− platform = ttUSHORT(fc+loc+0);
1484− if (platform != 0 && platform != 1)
1485− continue;
1486− name = ttUSHORT(fc+loc+6);
1487− if (name != 1 && name != 2) /* FIXME use 16 and 17? */
1488− continue;
1489− length = ttUSHORT(fc+loc+8);
1490− o = (char*)fc+stringOffset+ttUSHORT(fc+loc+10);
1491− if (platform == 0) {
1492− length = utf16to8((uchar*)tmp, sizeof(tmp), (uchar*)o, length);
1493− o = tmp;
1494− }
1495− if (name == 1)
1496− snprint(info->family, sizeof(info->family), "%.*s", length, o);
1497− else if (name == 2)
1498− snprint(info->subfamily, sizeof(info->subfamily), "%.*s", length, o);
1499− }
1500− }
1501−
15021464 // find a cmap encoding table we understand *now* to avoid searching
15031465 // later. (todo: could make this installable)
15041466 // the same regardless of glyph.
@@ -1531,64 +1493,6 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in · 26 unmodified lines
15311493 return 1;
15321494 }
15331495
1534−typedef struct stbtt_code2glyph stbtt_code2glyph;
1535−
1536−struct stbtt_code2glyph {
1537− u32int *code;
1538− u16int *glyph;
1539− int num;
1540−};
1541−
1542−STBTT_DEF stbtt_code2glyph *stbtt_Code2Glyph(const stbtt_fontinfo *info) {
1543− stbtt_uint8 *data = info->data;
1544− stbtt_uint32 index_map = info->index_map;
1545− stbtt_code2glyph *c2g;
1546− int i;
1547− stbtt_uint16 format = ttUSHORT(data + index_map + 0);
1548−
1549− if(format == 4) // FIXME
1550− return NULL;
1551−
1552− c2g = mallocz(sizeof(*c2g) + info->numGlyphs*6, 1);
1553− c2g->code = (u32int*)(c2g + 1);
1554− c2g->glyph = (u16int*)(c2g->code + info->numGlyphs);
1555− c2g->num = info->numGlyphs;
1556−
1557− if (format == 0) { // apple byte encoding
1558− stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
1559− for(i = 0; i < bytes-6; i++){
1560− c2g->code[i] = i;
1561− c2g->glyph[i] = ttBYTE(data + index_map + 6 + i);
1562− }
1563− } else if (format == 6) {
1564− stbtt_int32 first = ttUSHORT(data + index_map + 6);
1565− stbtt_int32 count = ttUSHORT(data + index_map + 8);
1566− for(i = 0; i < count; i++){
1567− c2g->code[i] = first + i;
1568− c2g->glyph[i] = ttUSHORT(data + index_map + 10 + i*2);
1569− }
1570− } else if (format == 2) {
1571− STBTT_assert(format == 2 && 0); // @TODO: high-byte mapping for japanese/chinese/korean
1572− } else if (format == 12 || format == 13) {
1573− stbtt_uint32 ngroups = ttULONG(data+index_map+12);
1574− stbtt_uint32 g, ch;
1575− for(i = 0, g = 0; g < ngroups; g++){
1576− stbtt_uint32 start_char = ttULONG(data+index_map+16+g*12);
1577− stbtt_uint32 end_char = ttULONG(data+index_map+16+g*12+4);
1578− stbtt_uint32 start_glyph = ttULONG(data+index_map+16+g*12+8);
1579− for(ch = start_char; ch <= end_char; ch++, i++){
1580− c2g->code[i] = ch;
1581− c2g->glyph[i] = format == 12 ? start_glyph+ch-start_char : start_glyph;
1582− }
1583− }
1584− } else {
1585− // @TODO
1586− STBTT_assert(0);
1587− }
1588−
1589− return c2g;
1590−}
1591−
15921496 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
15931497 {
15941498 stbtt_uint8 *data = info->data;
@@ -1640,12 +1544,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep · 45 unmodified lines
16401544 search += 2;
16411545
16421546 {
1643− stbtt_uint16 offset, start;
1547+ stbtt_uint16 offset, start, last;
16441548 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
16451549
1646− STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
16471550 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1648− if (unicode_codepoint < start)
1551+ last = ttUSHORT(data + endCount + 2*item);
1552+ if (unicode_codepoint < start || unicode_codepoint > last)
16491553 return 0;
16501554
16511555 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
@@ -1972,7 +1876,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s · 320 unmodified lines
19721876 if (comp_verts) STBTT_free(comp_verts, info->userdata);
19731877 return 0;
19741878 }
1975− if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
1879+ if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
19761880 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
19771881 if (vertices) STBTT_free(vertices, info->userdata);
19781882 vertices = tmp;
@@ -2235,7 +2139,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st · 256 unmodified lines
22352139 subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
22362140 has_subrs = 1;
22372141 }
2238− // fallthrough
2142+ // FALLTHROUGH
22392143 case 0x1D: // callgsubr
22402144 if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
22412145 v = (int) s[--sp];
@@ -2340,7 +2244,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st · 98 unmodified lines
23402244 } break;
23412245
23422246 default:
2343− if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
2247+ if (b0 != 255 && b0 != 28 && b0 < 32)
23442248 return STBTT__CSERR("reserved operator");
23452249
23462250 // push immediate
@@ -2452,7 +2356,7 @@ STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningent · 105 unmodified lines
24522356 return length;
24532357 }
24542358
2455−static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2359+static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
24562360 {
24572361 stbtt_uint8 *data = info->data + info->kern;
24582362 stbtt_uint32 needle, straw;
@@ -2482,247 +2386,225 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph · 23 unmodified lines
24822386 return 0;
24832387 }
24842388
2485−static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
2486−{
2487− stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2488− switch(coverageFormat) {
2489− case 1: {
2490− stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2491−
2492− // Binary search.
2493− stbtt_int32 l=0, r=glyphCount-1, m;
2494− int straw, needle=glyph;
2495− while (l <= r) {
2496− stbtt_uint8 *glyphArray = coverageTable + 4;
2497− stbtt_uint16 glyphID;
2498− m = (l + r) >> 1;
2499− glyphID = ttUSHORT(glyphArray + 2 * m);
2500− straw = glyphID;
2501− if (needle < straw)
2502− r = m - 1;
2503− else if (needle > straw)
2504− l = m + 1;
2505− else {
2506− return m;
2507− }
2389+static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
2390+{
2391+ stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2392+ switch (coverageFormat) {
2393+ case 1: {
2394+ stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2395+
2396+ // Binary search.
2397+ stbtt_int32 l=0, r=glyphCount-1, m;
2398+ int straw, needle=glyph;
2399+ while (l <= r) {
2400+ stbtt_uint8 *glyphArray = coverageTable + 4;
2401+ stbtt_uint16 glyphID;
2402+ m = (l + r) >> 1;
2403+ glyphID = ttUSHORT(glyphArray + 2 * m);
2404+ straw = glyphID;
2405+ if (needle < straw)
2406+ r = m - 1;
2407+ else if (needle > straw)
2408+ l = m + 1;
2409+ else {
2410+ return m;
25082411 }
2509− } break;
2510−
2511− case 2: {
2512− stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2513− stbtt_uint8 *rangeArray = coverageTable + 4;
2514−
2515− // Binary search.
2516− stbtt_int32 l=0, r=rangeCount-1, m;
2517− int strawStart, strawEnd, needle=glyph;
2518− while (l <= r) {
2519− stbtt_uint8 *rangeRecord;
2520− m = (l + r) >> 1;
2521− rangeRecord = rangeArray + 6 * m;
2522− strawStart = ttUSHORT(rangeRecord);
2523− strawEnd = ttUSHORT(rangeRecord + 2);
2524− if (needle < strawStart)
2525− r = m - 1;
2526− else if (needle > strawEnd)
2527− l = m + 1;
2528− else {
2529− stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2530− return startCoverageIndex + glyph - strawStart;
2531− }
2412+ }
2413+ break;
2414+ }
2415+
2416+ case 2: {
2417+ stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2418+ stbtt_uint8 *rangeArray = coverageTable + 4;
2419+
2420+ // Binary search.
2421+ stbtt_int32 l=0, r=rangeCount-1, m;
2422+ int strawStart, strawEnd, needle=glyph;
2423+ while (l <= r) {
2424+ stbtt_uint8 *rangeRecord;
2425+ m = (l + r) >> 1;
2426+ rangeRecord = rangeArray + 6 * m;
2427+ strawStart = ttUSHORT(rangeRecord);
2428+ strawEnd = ttUSHORT(rangeRecord + 2);
2429+ if (needle < strawStart)
2430+ r = m - 1;
2431+ else if (needle > strawEnd)
2432+ l = m + 1;
2433+ else {
2434+ stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2435+ return startCoverageIndex + glyph - strawStart;
25322436 }
2533− } break;
2437+ }
2438+ break;
2439+ }
25342440
2535− default: {
2536− // There are no other cases.
2537− STBTT_assert(0);
2538− } break;
2539− }
2441+ default: return -1; // unsupported
2442+ }
25402443
2541− return -1;
2444+ return -1;
25422445 }
25432446
25442447 static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
25452448 {
2546− stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2547− switch(classDefFormat)
2548− {
2549− case 1: {
2550− stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2551− stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2552− stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
2553−
2554− if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2555− return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2556−
2557− classDefTable = classDef1ValueArray + 2 * glyphCount;
2558− USED(classDefTable);
2559− } break;
2560−
2561− case 2: {
2562− stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2563− stbtt_uint8 *classRangeRecords = classDefTable + 4;
2564−
2565− // Binary search.
2566− stbtt_int32 l=0, r=classRangeCount-1, m;
2567− int strawStart, strawEnd, needle=glyph;
2568− while (l <= r) {
2569− stbtt_uint8 *classRangeRecord;
2570− m = (l + r) >> 1;
2571− classRangeRecord = classRangeRecords + 6 * m;
2572− strawStart = ttUSHORT(classRangeRecord);
2573− strawEnd = ttUSHORT(classRangeRecord + 2);
2574− if (needle < strawStart)
2575− r = m - 1;
2576− else if (needle > strawEnd)
2577− l = m + 1;
2578− else
2579− return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2580− }
2449+ stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2450+ switch (classDefFormat)
2451+ {
2452+ case 1: {
2453+ stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2454+ stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2455+ stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
25812456
2582− classDefTable = classRangeRecords + 6 * classRangeCount;
2583− USED(classDefTable);
2584− } break;
2457+ if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2458+ return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2459+ break;
2460+ }
25852461
2586− default: {
2587− // There are no other cases.
2588− STBTT_assert(0);
2589− } break;
2590− }
2462+ case 2: {
2463+ stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2464+ stbtt_uint8 *classRangeRecords = classDefTable + 4;
2465+
2466+ // Binary search.
2467+ stbtt_int32 l=0, r=classRangeCount-1, m;
2468+ int strawStart, strawEnd, needle=glyph;
2469+ while (l <= r) {
2470+ stbtt_uint8 *classRangeRecord;
2471+ m = (l + r) >> 1;
2472+ classRangeRecord = classRangeRecords + 6 * m;
2473+ strawStart = ttUSHORT(classRangeRecord);
2474+ strawEnd = ttUSHORT(classRangeRecord + 2);
2475+ if (needle < strawStart)
2476+ r = m - 1;
2477+ else if (needle > strawEnd)
2478+ l = m + 1;
2479+ else
2480+ return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2481+ }
2482+ break;
2483+ }
25912484
2592− return -1;
2485+ default:
2486+ return -1; // Unsupported definition type, return an error.
2487+ }
2488+
2489+ // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
2490+ return 0;
25932491 }
25942492
25952493 // Define to STBTT_assert(x) if you want to break on unimplemented formats.
25962494 #define STBTT_GPOS_TODO_assert(x)
25972495
2598−static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2599−{
2600− stbtt_uint16 lookupListOffset;
2601− stbtt_uint8 *lookupList;
2602− stbtt_uint16 lookupCount;
2603− stbtt_uint8 *data;
2604− stbtt_int32 i;
2605−
2606− if (!info->gpos) return 0;
2607−
2608− data = info->data + info->gpos;
2609−
2610− if (ttUSHORT(data+0) != 1) return 0; // Major version 1
2611− if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
2612−
2613− lookupListOffset = ttUSHORT(data+8);
2614− lookupList = data + lookupListOffset;
2615− lookupCount = ttUSHORT(lookupList);
2616−
2617− for (i=0; i<lookupCount; ++i) {
2618− stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2619− stbtt_uint8 *lookupTable = lookupList + lookupOffset;
2620−
2621− stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2622− stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2623− stbtt_uint8 *subTableOffsets = lookupTable + 6;
2624− switch(lookupType) {
2625− case 2: { // Pair Adjustment Positioning Subtable
2626− stbtt_int32 sti;
2627− for (sti=0; sti<subTableCount; sti++) {
2628− stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2629− stbtt_uint8 *table = lookupTable + subtableOffset;
2630− stbtt_uint16 posFormat = ttUSHORT(table);
2631− stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2632− stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2633− if (coverageIndex == -1) continue;
2634−
2635− switch (posFormat) {
2636− case 1: {
2637− stbtt_int32 l, r, m;
2638− int straw, needle;
2639− stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2640− stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2641− stbtt_int32 valueRecordPairSizeInBytes = 2;
2642− stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2643− stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2644− stbtt_uint8 *pairValueTable = table + pairPosOffset;
2645− stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2646− stbtt_uint8 *pairValueArray = pairValueTable + 2;
2647− // TODO: Support more formats.
2648− STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2649− if (valueFormat1 != 4) return 0;
2650− STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2651− if (valueFormat2 != 0) return 0;
2652−
2653− STBTT_assert(coverageIndex < pairSetCount);
2654− STBTT__NOTUSED(pairSetCount);
2655−
2656− needle=glyph2;
2657− r=pairValueCount-1;
2658− l=0;
2659−
2660− // Binary search.
2661− while (l <= r) {
2662− stbtt_uint16 secondGlyph;
2663− stbtt_uint8 *pairValue;
2664− m = (l + r) >> 1;
2665− pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2666− secondGlyph = ttUSHORT(pairValue);
2667− straw = secondGlyph;
2668− if (needle < straw)
2669− r = m - 1;
2670− else if (needle > straw)
2671− l = m + 1;
2672− else {
2673− stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2674− return xAdvance;
2675− }
2676− }
2677− } break;
2678−
2679− case 2: {
2680− stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2681− stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2682−
2683− stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2684− stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2685− int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2686− int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2687−
2688− stbtt_uint16 class1Count = ttUSHORT(table + 12);
2689− stbtt_uint16 class2Count = ttUSHORT(table + 14);
2690− if(glyph1class >= class1Count || glyph2class >= class2Count)
2691− return 0;
2692− STBTT_assert(glyph1class < class1Count);
2693− STBTT_assert(glyph2class < class2Count);
2694−
2695− // TODO: Support more formats.
2696− STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2697− if (valueFormat1 != 4) return 0;
2698− STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2699− if (valueFormat2 != 0) return 0;
2700−
2701− if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
2702− stbtt_uint8 *class1Records = table + 16;
2703− stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
2704− stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2705− return xAdvance;
2706− }
2707− } break;
2708−
2709− default: {
2710− // There are no other cases.
2711− STBTT_assert(0);
2712− break;
2713− };
2714− }
2715− }
2716− break;
2717− };
2496+static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2497+{
2498+ stbtt_uint16 lookupListOffset;
2499+ stbtt_uint8 *lookupList;
2500+ stbtt_uint16 lookupCount;
2501+ stbtt_uint8 *data;
2502+ stbtt_int32 i, sti;
2503+
2504+ if (!info->gpos) return 0;
2505+
2506+ data = info->data + info->gpos;
2507+
2508+ if (ttUSHORT(data+0) != 1) return 0; // Major version 1
2509+ if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
2510+
2511+ lookupListOffset = ttUSHORT(data+8);
2512+ lookupList = data + lookupListOffset;
2513+ lookupCount = ttUSHORT(lookupList);
2514+
2515+ for (i=0; i<lookupCount; ++i) {
2516+ stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2517+ stbtt_uint8 *lookupTable = lookupList + lookupOffset;
2518+
2519+ stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2520+ stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2521+ stbtt_uint8 *subTableOffsets = lookupTable + 6;
2522+ if (lookupType != 2) // Pair Adjustment Positioning Subtable
2523+ continue;
2524+
2525+ for (sti=0; sti<subTableCount; sti++) {
2526+ stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2527+ stbtt_uint8 *table = lookupTable + subtableOffset;
2528+ stbtt_uint16 posFormat = ttUSHORT(table);
2529+ stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2530+ stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2531+ if (coverageIndex == -1) continue;
2532+
2533+ switch (posFormat) {
2534+ case 1: {
2535+ stbtt_int32 l, r, m;
2536+ int straw, needle;
2537+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2538+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2539+ if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
2540+ stbtt_int32 valueRecordPairSizeInBytes = 2;
2541+ stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2542+ stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2543+ stbtt_uint8 *pairValueTable = table + pairPosOffset;
2544+ stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2545+ stbtt_uint8 *pairValueArray = pairValueTable + 2;
2546+
2547+ if (coverageIndex >= pairSetCount) return 0;
2548+
2549+ needle=glyph2;
2550+ r=pairValueCount-1;
2551+ l=0;
2552+
2553+ // Binary search.
2554+ while (l <= r) {
2555+ stbtt_uint16 secondGlyph;
2556+ stbtt_uint8 *pairValue;
2557+ m = (l + r) >> 1;
2558+ pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2559+ secondGlyph = ttUSHORT(pairValue);
2560+ straw = secondGlyph;
2561+ if (needle < straw)
2562+ r = m - 1;
2563+ else if (needle > straw)
2564+ l = m + 1;
2565+ else {
2566+ stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2567+ return xAdvance;
2568+ }
2569+ }
2570+ } else
2571+ return 0;
2572+ break;
2573+ }
2574+
2575+ case 2: {
2576+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2577+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2578+ if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
2579+ stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2580+ stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2581+ int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2582+ int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2583+
2584+ stbtt_uint16 class1Count = ttUSHORT(table + 12);
2585+ stbtt_uint16 class2Count = ttUSHORT(table + 14);
2586+ stbtt_uint8 *class1Records, *class2Records;
2587+ stbtt_int16 xAdvance;
2588+
2589+ if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
2590+ if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
2591+
2592+ class1Records = table + 16;
2593+ class2Records = class1Records + 2 * (glyph1class * class2Count);
2594+ xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2595+ return xAdvance;
2596+ } else
2597+ return 0;
2598+ break;
2599+ }
27182600
27192601 default:
2720− // TODO: Implement other stuff.
2721− break;
2722− }
2723− }
2602+ return 0; // Unsupported position format
2603+ }
2604+ }
2605+ }
27242606
2725− return 0;
2607+ return 0;
27262608 }
27272609
27282610 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
@@ -2731,7 +2613,7 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int · 2 unmodified lines
27312613
27322614 if (info->gpos)
27332615 xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
2734− if (info->kern && xAdvance == 0)
2616+ else if (info->kern)
27352617 xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
27362618
27372619 return xAdvance;
@@ -2789,7 +2671,6 @@ STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, floa · 51 unmodified lines
27892671
27902672 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
27912673 {
2792− USED(info);
27932674 STBTT_free(v, info->userdata);
27942675 }
27952676
@@ -3173,14 +3054,30 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg · 377 unmodified lines
31733054
31743055 if (x0 <= x && x1 <= x)
31753056 scanline[x] += e->direction * (y1-y0);
3176− else if (x0 >= x+1 && x1 >= x+1)
3177− {}
3178− else {
3057+ else if (x0 >= x+1 && x1 >= x+1) {
3058+ } else {
31793059 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
31803060 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
31813061 }
31823062 }
31833063
3064+static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
3065+{
3066+ STBTT_assert(top_width >= 0);
3067+ STBTT_assert(bottom_width >= 0);
3068+ return (top_width + bottom_width) / 2.0f * height;
3069+}
3070+
3071+static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
3072+{
3073+ return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
3074+}
3075+
3076+static float stbtt__sized_triangle_area(float height, float width)
3077+{
3078+ return height * width / 2;
3079+}
3080+
31843081 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
31853082 {
31863083 float y_bottom = y_top+1;
@@ -3235,13 +3132,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, · 48 unmodified lines
32353132 float height;
32363133 // simple case, only spans one pixel
32373134 int x = (int) x_top;
3238− height = sy1 - sy0;
3135+ height = (sy1 - sy0) * e->direction;
32393136 STBTT_assert(x >= 0 && x < len);
3240− scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
3241− scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
3137+ scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
3138+ scanline_fill[x] += height; // everything right of this pixel is filled
32423139 } else {
32433140 int x,x1,x2;
3244− float y_crossing, step, sign, area;
3141+ float y_crossing, y_final, step, sign, area;
32453142 // covers 2+ pixels
32463143 if (x_top > x_bottom) {
32473144 // flip scanline vertically; signed area is the same
@@ -3252,32 +3149,81 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, · 4 unmodified lines
32523149 t = x_bottom, x_bottom = x_top, x_top = t;
32533150 dx = -dx;
32543151 dy = -dy;
3255− t = x0, x0 = xb, xb = t;
3256− USED(dx); USED(xb);
3152+ x0 = xb;
32573153 }
3154+ STBTT_assert(dy >= 0);
3155+ STBTT_assert(dx >= 0);
32583156
32593157 x1 = (int) x_top;
32603158 x2 = (int) x_bottom;
32613159 // compute intersection with y axis at x1+1
3262− y_crossing = (x1+1 - x0) * dy + y_top;
3160+ y_crossing = y_top + dy * (x1+1 - x0);
3161+
3162+ // compute intersection with y axis at x2
3163+ y_final = y_top + dy * (x2 - x0);
3164+
3165+ // x1 x_top x2 x_bottom
3166+ // y_top +------|-----+------------+------------+--------|---+------------+
3167+ // | | | | | |
3168+ // | | | | | |
3169+ // sy0 | Txxxxx|............|............|............|............|
3170+ // y_crossing | *xxxxx.......|............|............|............|
3171+ // | | xxxxx..|............|............|............|
3172+ // | | /- xx*xxxx........|............|............|
3173+ // | | dy < | xxxxxx..|............|............|
3174+ // y_final | | \- | xx*xxx.........|............|
3175+ // sy1 | | | | xxxxxB...|............|
3176+ // | | | | | |
3177+ // | | | | | |
3178+ // y_bottom +------------+------------+------------+------------+------------+
3179+ //
3180+ // goal is to measure the area covered by '.' in each pixel
3181+
3182+ // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
3183+ // @TODO: maybe test against sy1 rather than y_bottom?
3184+ if (y_crossing > y_bottom)
3185+ y_crossing = y_bottom;
32633186
32643187 sign = e->direction;
3265− // area of the rectangle covered from y0..y_crossing
3188+
3189+ // area of the rectangle covered from sy0..y_crossing
32663190 area = sign * (y_crossing-sy0);
3267− // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
3268− scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
32693191
3270− step = sign * dy;
3192+ // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
3193+ scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
3194+
3195+ // check if final y_crossing is blown up; no test case for this
3196+ if (y_final > y_bottom) {
3197+ y_final = y_bottom;
3198+ dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
3199+ }
3200+
3201+ // in second pixel, area covered by line segment found in first pixel
3202+ // is always a rectangle 1 wide * the height of that line segment; this
3203+ // is exactly what the variable 'area' stores. it also gets a contribution
3204+ // from the line segment within it. the THIRD pixel will get the first
3205+ // pixel's rectangle contribution, the second pixel's rectangle contribution,
3206+ // and its own contribution. the 'own contribution' is the same in every pixel except
3207+ // the leftmost and rightmost, a trapezoid that slides down in each pixel.
3208+ // the second pixel's contribution to the third pixel will be the
3209+ // rectangle 1 wide times the height change in the second pixel, which is dy.
3210+
3211+ step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
3212+ // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
3213+ // so the area advances by 'step' every time
3214+
32713215 for (x = x1+1; x < x2; ++x) {
3272− scanline[x] += area + step/2;
3216+ scanline[x] += area + step/2; // area of trapezoid is 1*step/2
32733217 area += step;
32743218 }
3275− y_crossing += dy * (x2 - (x1+1));
3219+ STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
3220+ STBTT_assert(sy1 > y_final-0.01f);
32763221
3277− STBTT_assert(STBTT_fabs(area) <= 1.01f);
3278−
3279− scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
3222+ // area covered in the last pixel is the rectangle from all the pixels to the left,
3223+ // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
3224+ scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
32803225
3226+ // the rest of the line is filled based on the total height of the line segment in this pixel
32813227 scanline_fill[x2] += sign * (sy1-sy0);
32823228 }
32833229 } else {
@@ -3285,6 +3231,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, · 1 unmodified line
32853231 // clipping logic. since this does not match the intended use
32863232 // of this library, we use a different, very slow brute
32873233 // force implementation
3234+ // note though that this does happen some of the time because
3235+ // x_top and x_bottom can be extrapolated at the top & bottom of
3236+ // the shape and actually lie outside the bounding box
32883237 int x;
32893238 for (x=0; x < len; ++x) {
32903239 // cases:
@@ -4521,15 +4470,14 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex · 1230 unmodified lines
45214470 float y_frac;
45224471 int winding = 0;
45234472
4524− orig[0] = x;
4525− orig[1] = y;
4526−
45274473 // make sure y never passes through a vertex of the shape
45284474 y_frac = (float) STBTT_fmod(y, 1.0f);
45294475 if (y_frac < 0.01f)
45304476 y += 0.01f;
45314477 else if (y_frac > 0.99f)
45324478 y -= 0.01f;
4479+
4480+ orig[0] = x;
45334481 orig[1] = y;
45344482
45354483 // test a ray from (-infinity,y) to (x,y)
@@ -4591,35 +4539,35 @@ static float stbtt__cuberoot( float x ) · 55 unmodified lines
45914539 return (float) STBTT_pow( x,1.0f/3.0f);
45924540 }
45934541
4594−// x^3 + c*x^2 + b*x + a = 0
4542+// x^3 + a*x^2 + b*x + c = 0
45954543 static int stbtt__solve_cubic(float a, float b, float c, float* r)
45964544 {
4597− float s = -a / 3;
4598− float p = b - a*a / 3;
4599− float q = a * (2*a*a - 9*b) / 27 + c;
4545+ float s = -a / 3;
4546+ float p = b - a*a / 3;
4547+ float q = a * (2*a*a - 9*b) / 27 + c;
46004548 float p3 = p*p*p;
4601− float d = q*q + 4*p3 / 27;
4602− if (d >= 0) {
4603− float z = (float) STBTT_sqrt(d);
4604− float u = (-q + z) / 2;
4605− float v = (-q - z) / 2;
4606− u = stbtt__cuberoot(u);
4607− v = stbtt__cuberoot(v);
4608− r[0] = s + u + v;
4609− return 1;
4610− } else {
4611− float u = (float) STBTT_sqrt(-p/3);
4612− float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
4613− float m = (float) STBTT_cos(v);
4549+ float d = q*q + 4*p3 / 27;
4550+ if (d >= 0) {
4551+ float z = (float) STBTT_sqrt(d);
4552+ float u = (-q + z) / 2;
4553+ float v = (-q - z) / 2;
4554+ u = stbtt__cuberoot(u);
4555+ v = stbtt__cuberoot(v);
4556+ r[0] = s + u + v;
4557+ return 1;
4558+ } else {
4559+ float u = (float) STBTT_sqrt(-p/3);
4560+ float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
4561+ float m = (float) STBTT_cos(v);
46144562 float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
4615− r[0] = s + u * 2 * m;
4616− r[1] = s - u * (m + n);
4617− r[2] = s - u * (m - n);
4563+ r[0] = s + u * 2 * m;
4564+ r[1] = s - u * (m + n);
4565+ r[2] = s - u * (m - n);
46184566
46194567 //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
46204568 //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
46214569 //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
4622− return 3;
4570+ return 3;
46234571 }
46244572 }
46254573
@@ -4696,18 +4644,17 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc · 70 unmodified lines
46964644 for (i=0; i < num_verts; ++i) {
46974645 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
46984646
4699− // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
4700− float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4701− if (dist2 < min_dist*min_dist)
4702− min_dist = (float) STBTT_sqrt(dist2);
4703−
4704− if (verts[i].type == STBTT_vline) {
4647+ if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
47054648 float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
47064649
4650+ float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4651+ if (dist2 < min_dist*min_dist)
4652+ min_dist = (float) STBTT_sqrt(dist2);
4653+
47074654 // coarse culling against bbox
47084655 //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
47094656 // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
4710− float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
4657+ dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
47114658 STBTT_assert(i != 0);
47124659 if (dist < min_dist) {
47134660 // check position along line
@@ -4734,7 +4681,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc · 20 unmodified lines
47344681 float ax = x1-x0, ay = y1-y0;
47354682 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
47364683 float mx = x0 - sx, my = y0 - sy;
4737− float res[3],px,py,t,it;
4684+ float res[3] = {0.f,0.f,0.f};
4685+ float px,py,t,it,dist2;
47384686 float a_inv = precompute[i];
47394687 if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
47404688 float a = 3*(ax*bx + ay*by);
@@ -4761,6 +4709,10 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc · 20 unmodified lines
47614709 float d = (mx*ax+my*ay) * a_inv;
47624710 num = stbtt__solve_cubic(b, c, d, res);
47634711 }
4712+ dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4713+ if (dist2 < min_dist*min_dist)
4714+ min_dist = (float) STBTT_sqrt(dist2);
4715+
47644716 if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
47654717 t = res[0], it = 1.0f - t;
47664718 px = it*it*x0 + 2*t*it*x1 + t*t*x2;
@@ -5020,6 +4972,12 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const · 253 unmodified lines
50204972
50214973 // FULL VERSION HISTORY
50224974 //
4975+// 1.25 (2021-07-11) many fixes
4976+// 1.24 (2020-02-05) fix warning
4977+// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
4978+// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
4979+// 1.21 (2019-02-25) fix warning
4980+// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
50234981 // 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
50244982 // 1.18 (2018-01-29) add missing function
50254983 // 1.17 (2017-07-23) make more arguments const; doc fix

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t