gosu 1.4.1 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/dependencies/SDL_sound/SDL_sound.c +21 -63
  3. data/dependencies/SDL_sound/SDL_sound.h +2 -2
  4. data/dependencies/SDL_sound/SDL_sound_aiff.c +26 -23
  5. data/dependencies/SDL_sound/SDL_sound_au.c +8 -8
  6. data/dependencies/SDL_sound/SDL_sound_coreaudio.c +4 -5
  7. data/dependencies/SDL_sound/SDL_sound_flac.c +28 -30
  8. data/dependencies/SDL_sound/SDL_sound_internal.h +4 -4
  9. data/dependencies/SDL_sound/SDL_sound_modplug.c +1 -1
  10. data/dependencies/SDL_sound/SDL_sound_mp3.c +19 -23
  11. data/dependencies/SDL_sound/SDL_sound_raw.c +5 -6
  12. data/dependencies/SDL_sound/SDL_sound_shn.c +4 -4
  13. data/dependencies/SDL_sound/SDL_sound_voc.c +15 -15
  14. data/dependencies/SDL_sound/SDL_sound_vorbis.c +14 -7
  15. data/dependencies/SDL_sound/SDL_sound_wav.c +17 -17
  16. data/dependencies/SDL_sound/dr_flac.h +10840 -4779
  17. data/dependencies/SDL_sound/dr_mp3.h +2793 -1004
  18. data/dependencies/SDL_sound/libmodplug/fastmix.c +5 -0
  19. data/dependencies/SDL_sound/libmodplug/load_669.c +1 -1
  20. data/dependencies/SDL_sound/libmodplug/load_amf.c +1 -0
  21. data/dependencies/SDL_sound/libmodplug/load_ams.c +38 -22
  22. data/dependencies/SDL_sound/libmodplug/load_it.c +18 -14
  23. data/dependencies/SDL_sound/libmodplug/load_mdl.c +18 -9
  24. data/dependencies/SDL_sound/libmodplug/load_med.c +7 -6
  25. data/dependencies/SDL_sound/libmodplug/load_mt2.c +36 -17
  26. data/dependencies/SDL_sound/libmodplug/load_okt.c +51 -24
  27. data/dependencies/SDL_sound/libmodplug/load_psm.c +4 -2
  28. data/dependencies/SDL_sound/libmodplug/load_s3m.c +4 -4
  29. data/dependencies/SDL_sound/libmodplug/load_ult.c +4 -3
  30. data/dependencies/SDL_sound/libmodplug/load_xm.c +5 -5
  31. data/dependencies/SDL_sound/libmodplug/snd_fx.c +8 -1
  32. data/dependencies/SDL_sound/libmodplug/sndfile.c +21 -4
  33. data/dependencies/SDL_sound/stb_vorbis.h +10 -18
  34. data/dependencies/mojoAL/mojoal.c +260 -6
  35. data/dependencies/stb/stb_image.h +208 -73
  36. data/dependencies/stb/stb_image_write.h +57 -23
  37. data/dependencies/stb/stb_truetype.h +345 -279
  38. data/dependencies/utf8proc/utf8proc.c +37 -18
  39. data/dependencies/utf8proc/utf8proc.h +17 -5
  40. data/dependencies/utf8proc/utf8proc_data.h +12012 -10089
  41. data/include/Gosu/Buttons.hpp +103 -103
  42. data/include/Gosu/Directories.hpp +31 -24
  43. data/include/Gosu/Font.hpp +4 -2
  44. data/include/Gosu/Gosu.hpp +5 -8
  45. data/include/Gosu/IO.hpp +0 -3
  46. data/include/Gosu/Math.hpp +0 -3
  47. data/include/Gosu/Timing.hpp +2 -8
  48. data/include/Gosu/Version.hpp +1 -1
  49. data/src/AudioImpl.cpp +0 -7
  50. data/src/AudioImpl.hpp +1 -3
  51. data/src/BitmapIO.cpp +23 -2
  52. data/src/DirectoriesApple.cpp +25 -24
  53. data/src/DirectoriesUnix.cpp +14 -12
  54. data/src/DirectoriesWin.cpp +26 -30
  55. data/src/Font.cpp +12 -2
  56. data/src/Image.cpp +10 -15
  57. data/src/RubyGosu.cxx +6 -34
  58. data/src/TimingApple.cpp +1 -7
  59. data/src/TimingUnix.cpp +0 -6
  60. data/src/TimingWin.cpp +0 -6
  61. data/src/Window.cpp +4 -3
  62. metadata +2 -2
@@ -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
3
3
  //
4
4
  // =======================================================================
5
5
  //
@@ -58,6 +58,8 @@
58
58
  //
59
59
  // VERSION HISTORY
60
60
  //
61
+ // 1.26 (2021-08-28) fix broken rasterizer
62
+ // 1.25 (2021-07-11) many fixes
61
63
  // 1.24 (2020-02-05) fix warning
62
64
  // 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
63
65
  // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
@@ -270,8 +272,8 @@
270
272
  //// SAMPLE PROGRAMS
271
273
  ////
272
274
  //
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.
275
277
  #if 0
276
278
  #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
277
279
  #include "stb_truetype.h"
@@ -297,6 +299,8 @@ void my_stbtt_initfont(void)
297
299
  void my_stbtt_print(float x, float y, char *text)
298
300
  {
299
301
  // 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);
300
304
  glEnable(GL_TEXTURE_2D);
301
305
  glBindTexture(GL_TEXTURE_2D, ftex);
302
306
  glBegin(GL_QUADS);
@@ -304,10 +308,10 @@ void my_stbtt_print(float x, float y, char *text)
304
308
  if (*text >= 32 && *text < 128) {
305
309
  stbtt_aligned_quad q;
306
310
  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);
311
315
  }
312
316
  ++text;
313
317
  }
@@ -853,6 +857,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
853
857
  STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
854
858
  // frees the data allocated above
855
859
 
860
+ STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
856
861
  STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
857
862
  STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
858
863
  // fills svg with the character's SVG data.
@@ -1539,12 +1544,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
1539
1544
  search += 2;
1540
1545
 
1541
1546
  {
1542
- stbtt_uint16 offset, start;
1547
+ stbtt_uint16 offset, start, last;
1543
1548
  stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
1544
1549
 
1545
- STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
1546
1550
  start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
1547
- if (unicode_codepoint < start)
1551
+ last = ttUSHORT(data + endCount + 2*item);
1552
+ if (unicode_codepoint < start || unicode_codepoint > last)
1548
1553
  return 0;
1549
1554
 
1550
1555
  offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
@@ -1871,7 +1876,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
1871
1876
  if (comp_verts) STBTT_free(comp_verts, info->userdata);
1872
1877
  return 0;
1873
1878
  }
1874
- 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));
1875
1880
  STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
1876
1881
  if (vertices) STBTT_free(vertices, info->userdata);
1877
1882
  vertices = tmp;
@@ -2134,7 +2139,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
2134
2139
  subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
2135
2140
  has_subrs = 1;
2136
2141
  }
2137
- // fallthrough
2142
+ // FALLTHROUGH
2138
2143
  case 0x1D: // callgsubr
2139
2144
  if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
2140
2145
  v = (int) s[--sp];
@@ -2239,7 +2244,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
2239
2244
  } break;
2240
2245
 
2241
2246
  default:
2242
- if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
2247
+ if (b0 != 255 && b0 != 28 && b0 < 32)
2243
2248
  return STBTT__CSERR("reserved operator");
2244
2249
 
2245
2250
  // push immediate
@@ -2351,7 +2356,7 @@ STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningent
2351
2356
  return length;
2352
2357
  }
2353
2358
 
2354
- 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)
2355
2360
  {
2356
2361
  stbtt_uint8 *data = info->data + info->kern;
2357
2362
  stbtt_uint32 needle, straw;
@@ -2381,243 +2386,225 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph
2381
2386
  return 0;
2382
2387
  }
2383
2388
 
2384
- static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
2385
- {
2386
- stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
2387
- switch(coverageFormat) {
2388
- case 1: {
2389
- stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
2390
-
2391
- // Binary search.
2392
- stbtt_int32 l=0, r=glyphCount-1, m;
2393
- int straw, needle=glyph;
2394
- while (l <= r) {
2395
- stbtt_uint8 *glyphArray = coverageTable + 4;
2396
- stbtt_uint16 glyphID;
2397
- m = (l + r) >> 1;
2398
- glyphID = ttUSHORT(glyphArray + 2 * m);
2399
- straw = glyphID;
2400
- if (needle < straw)
2401
- r = m - 1;
2402
- else if (needle > straw)
2403
- l = m + 1;
2404
- else {
2405
- return m;
2406
- }
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;
2407
2411
  }
2408
- } break;
2409
-
2410
- case 2: {
2411
- stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
2412
- stbtt_uint8 *rangeArray = coverageTable + 4;
2413
-
2414
- // Binary search.
2415
- stbtt_int32 l=0, r=rangeCount-1, m;
2416
- int strawStart, strawEnd, needle=glyph;
2417
- while (l <= r) {
2418
- stbtt_uint8 *rangeRecord;
2419
- m = (l + r) >> 1;
2420
- rangeRecord = rangeArray + 6 * m;
2421
- strawStart = ttUSHORT(rangeRecord);
2422
- strawEnd = ttUSHORT(rangeRecord + 2);
2423
- if (needle < strawStart)
2424
- r = m - 1;
2425
- else if (needle > strawEnd)
2426
- l = m + 1;
2427
- else {
2428
- stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
2429
- return startCoverageIndex + glyph - strawStart;
2430
- }
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;
2431
2436
  }
2432
- } break;
2437
+ }
2438
+ break;
2439
+ }
2433
2440
 
2434
- default: {
2435
- // There are no other cases.
2436
- STBTT_assert(0);
2437
- } break;
2438
- }
2441
+ default: return -1; // unsupported
2442
+ }
2439
2443
 
2440
- return -1;
2444
+ return -1;
2441
2445
  }
2442
2446
 
2443
2447
  static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
2444
2448
  {
2445
- stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
2446
- switch(classDefFormat)
2447
- {
2448
- case 1: {
2449
- stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
2450
- stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
2451
- stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
2452
-
2453
- if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2454
- return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2455
-
2456
- classDefTable = classDef1ValueArray + 2 * glyphCount;
2457
- } break;
2458
-
2459
- case 2: {
2460
- stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
2461
- stbtt_uint8 *classRangeRecords = classDefTable + 4;
2462
-
2463
- // Binary search.
2464
- stbtt_int32 l=0, r=classRangeCount-1, m;
2465
- int strawStart, strawEnd, needle=glyph;
2466
- while (l <= r) {
2467
- stbtt_uint8 *classRangeRecord;
2468
- m = (l + r) >> 1;
2469
- classRangeRecord = classRangeRecords + 6 * m;
2470
- strawStart = ttUSHORT(classRangeRecord);
2471
- strawEnd = ttUSHORT(classRangeRecord + 2);
2472
- if (needle < strawStart)
2473
- r = m - 1;
2474
- else if (needle > strawEnd)
2475
- l = m + 1;
2476
- else
2477
- return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
2478
- }
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;
2479
2456
 
2480
- classDefTable = classRangeRecords + 6 * classRangeCount;
2481
- } break;
2457
+ if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
2458
+ return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
2459
+ break;
2460
+ }
2482
2461
 
2483
- default: {
2484
- // There are no other cases.
2485
- STBTT_assert(0);
2486
- } break;
2487
- }
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
+ }
2488
2484
 
2489
- 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;
2490
2491
  }
2491
2492
 
2492
2493
  // Define to STBTT_assert(x) if you want to break on unimplemented formats.
2493
2494
  #define STBTT_GPOS_TODO_assert(x)
2494
2495
 
2495
- static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
2496
- {
2497
- stbtt_uint16 lookupListOffset;
2498
- stbtt_uint8 *lookupList;
2499
- stbtt_uint16 lookupCount;
2500
- stbtt_uint8 *data;
2501
- stbtt_int32 i;
2502
-
2503
- if (!info->gpos) return 0;
2504
-
2505
- data = info->data + info->gpos;
2506
-
2507
- if (ttUSHORT(data+0) != 1) return 0; // Major version 1
2508
- if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
2509
-
2510
- lookupListOffset = ttUSHORT(data+8);
2511
- lookupList = data + lookupListOffset;
2512
- lookupCount = ttUSHORT(lookupList);
2513
-
2514
- for (i=0; i<lookupCount; ++i) {
2515
- stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
2516
- stbtt_uint8 *lookupTable = lookupList + lookupOffset;
2517
-
2518
- stbtt_uint16 lookupType = ttUSHORT(lookupTable);
2519
- stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
2520
- stbtt_uint8 *subTableOffsets = lookupTable + 6;
2521
- switch(lookupType) {
2522
- case 2: { // Pair Adjustment Positioning Subtable
2523
- stbtt_int32 sti;
2524
- for (sti=0; sti<subTableCount; sti++) {
2525
- stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
2526
- stbtt_uint8 *table = lookupTable + subtableOffset;
2527
- stbtt_uint16 posFormat = ttUSHORT(table);
2528
- stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
2529
- stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
2530
- if (coverageIndex == -1) continue;
2531
-
2532
- switch (posFormat) {
2533
- case 1: {
2534
- stbtt_int32 l, r, m;
2535
- int straw, needle;
2536
- stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2537
- stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2538
- stbtt_int32 valueRecordPairSizeInBytes = 2;
2539
- stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
2540
- stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
2541
- stbtt_uint8 *pairValueTable = table + pairPosOffset;
2542
- stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
2543
- stbtt_uint8 *pairValueArray = pairValueTable + 2;
2544
- // TODO: Support more formats.
2545
- STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2546
- if (valueFormat1 != 4) return 0;
2547
- STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2548
- if (valueFormat2 != 0) return 0;
2549
-
2550
- STBTT_assert(coverageIndex < pairSetCount);
2551
- STBTT__NOTUSED(pairSetCount);
2552
-
2553
- needle=glyph2;
2554
- r=pairValueCount-1;
2555
- l=0;
2556
-
2557
- // Binary search.
2558
- while (l <= r) {
2559
- stbtt_uint16 secondGlyph;
2560
- stbtt_uint8 *pairValue;
2561
- m = (l + r) >> 1;
2562
- pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
2563
- secondGlyph = ttUSHORT(pairValue);
2564
- straw = secondGlyph;
2565
- if (needle < straw)
2566
- r = m - 1;
2567
- else if (needle > straw)
2568
- l = m + 1;
2569
- else {
2570
- stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
2571
- return xAdvance;
2572
- }
2573
- }
2574
- } break;
2575
-
2576
- case 2: {
2577
- stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
2578
- stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
2579
-
2580
- stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
2581
- stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
2582
- int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
2583
- int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
2584
-
2585
- stbtt_uint16 class1Count = ttUSHORT(table + 12);
2586
- stbtt_uint16 class2Count = ttUSHORT(table + 14);
2587
- STBTT_assert(glyph1class < class1Count);
2588
- STBTT_assert(glyph2class < class2Count);
2589
-
2590
- // TODO: Support more formats.
2591
- STBTT_GPOS_TODO_assert(valueFormat1 == 4);
2592
- if (valueFormat1 != 4) return 0;
2593
- STBTT_GPOS_TODO_assert(valueFormat2 == 0);
2594
- if (valueFormat2 != 0) return 0;
2595
-
2596
- if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
2597
- stbtt_uint8 *class1Records = table + 16;
2598
- stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
2599
- stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
2600
- return xAdvance;
2601
- }
2602
- } break;
2603
-
2604
- default: {
2605
- // There are no other cases.
2606
- STBTT_assert(0);
2607
- break;
2608
- };
2609
- }
2610
- }
2611
- break;
2612
- };
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
+ }
2613
2600
 
2614
2601
  default:
2615
- // TODO: Implement other stuff.
2616
- break;
2617
- }
2618
- }
2602
+ return 0; // Unsupported position format
2603
+ }
2604
+ }
2605
+ }
2619
2606
 
2620
- return 0;
2607
+ return 0;
2621
2608
  }
2622
2609
 
2623
2610
  STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
@@ -3075,6 +3062,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg
3075
3062
  }
3076
3063
  }
3077
3064
 
3065
+ static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
3066
+ {
3067
+ STBTT_assert(top_width >= 0);
3068
+ STBTT_assert(bottom_width >= 0);
3069
+ return (top_width + bottom_width) / 2.0f * height;
3070
+ }
3071
+
3072
+ static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
3073
+ {
3074
+ return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
3075
+ }
3076
+
3077
+ static float stbtt__sized_triangle_area(float height, float width)
3078
+ {
3079
+ return height * width / 2;
3080
+ }
3081
+
3078
3082
  static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
3079
3083
  {
3080
3084
  float y_bottom = y_top+1;
@@ -3129,13 +3133,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
3129
3133
  float height;
3130
3134
  // simple case, only spans one pixel
3131
3135
  int x = (int) x_top;
3132
- height = sy1 - sy0;
3136
+ height = (sy1 - sy0) * e->direction;
3133
3137
  STBTT_assert(x >= 0 && x < len);
3134
- scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
3135
- scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
3138
+ scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
3139
+ scanline_fill[x] += height; // everything right of this pixel is filled
3136
3140
  } else {
3137
3141
  int x,x1,x2;
3138
- float y_crossing, step, sign, area;
3142
+ float y_crossing, y_final, step, sign, area;
3139
3143
  // covers 2+ pixels
3140
3144
  if (x_top > x_bottom) {
3141
3145
  // flip scanline vertically; signed area is the same
@@ -3148,29 +3152,79 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
3148
3152
  dy = -dy;
3149
3153
  t = x0, x0 = xb, xb = t;
3150
3154
  }
3155
+ STBTT_assert(dy >= 0);
3156
+ STBTT_assert(dx >= 0);
3151
3157
 
3152
3158
  x1 = (int) x_top;
3153
3159
  x2 = (int) x_bottom;
3154
3160
  // compute intersection with y axis at x1+1
3155
- y_crossing = (x1+1 - x0) * dy + y_top;
3161
+ y_crossing = y_top + dy * (x1+1 - x0);
3162
+
3163
+ // compute intersection with y axis at x2
3164
+ y_final = y_top + dy * (x2 - x0);
3165
+
3166
+ // x1 x_top x2 x_bottom
3167
+ // y_top +------|-----+------------+------------+--------|---+------------+
3168
+ // | | | | | |
3169
+ // | | | | | |
3170
+ // sy0 | Txxxxx|............|............|............|............|
3171
+ // y_crossing | *xxxxx.......|............|............|............|
3172
+ // | | xxxxx..|............|............|............|
3173
+ // | | /- xx*xxxx........|............|............|
3174
+ // | | dy < | xxxxxx..|............|............|
3175
+ // y_final | | \- | xx*xxx.........|............|
3176
+ // sy1 | | | | xxxxxB...|............|
3177
+ // | | | | | |
3178
+ // | | | | | |
3179
+ // y_bottom +------------+------------+------------+------------+------------+
3180
+ //
3181
+ // goal is to measure the area covered by '.' in each pixel
3182
+
3183
+ // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
3184
+ // @TODO: maybe test against sy1 rather than y_bottom?
3185
+ if (y_crossing > y_bottom)
3186
+ y_crossing = y_bottom;
3156
3187
 
3157
3188
  sign = e->direction;
3158
- // area of the rectangle covered from y0..y_crossing
3189
+
3190
+ // area of the rectangle covered from sy0..y_crossing
3159
3191
  area = sign * (y_crossing-sy0);
3160
- // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
3161
- scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
3162
3192
 
3163
- step = sign * dy;
3193
+ // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
3194
+ scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
3195
+
3196
+ // check if final y_crossing is blown up; no test case for this
3197
+ if (y_final > y_bottom) {
3198
+ y_final = y_bottom;
3199
+ dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom
3200
+ }
3201
+
3202
+ // in second pixel, area covered by line segment found in first pixel
3203
+ // is always a rectangle 1 wide * the height of that line segment; this
3204
+ // is exactly what the variable 'area' stores. it also gets a contribution
3205
+ // from the line segment within it. the THIRD pixel will get the first
3206
+ // pixel's rectangle contribution, the second pixel's rectangle contribution,
3207
+ // and its own contribution. the 'own contribution' is the same in every pixel except
3208
+ // the leftmost and rightmost, a trapezoid that slides down in each pixel.
3209
+ // the second pixel's contribution to the third pixel will be the
3210
+ // rectangle 1 wide times the height change in the second pixel, which is dy.
3211
+
3212
+ step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
3213
+ // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
3214
+ // so the area advances by 'step' every time
3215
+
3164
3216
  for (x = x1+1; x < x2; ++x) {
3165
- scanline[x] += area + step/2;
3217
+ scanline[x] += area + step/2; // area of trapezoid is 1*step/2
3166
3218
  area += step;
3167
3219
  }
3168
- y_crossing += dy * (x2 - (x1+1));
3169
-
3170
- STBTT_assert(STBTT_fabs(area) <= 1.01f);
3220
+ STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
3221
+ STBTT_assert(sy1 > y_final-0.01f);
3171
3222
 
3172
- scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
3223
+ // area covered in the last pixel is the rectangle from all the pixels to the left,
3224
+ // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
3225
+ scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
3173
3226
 
3227
+ // the rest of the line is filled based on the total height of the line segment in this pixel
3174
3228
  scanline_fill[x2] += sign * (sy1-sy0);
3175
3229
  }
3176
3230
  } else {
@@ -3178,6 +3232,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
3178
3232
  // clipping logic. since this does not match the intended use
3179
3233
  // of this library, we use a different, very slow brute
3180
3234
  // force implementation
3235
+ // note though that this does happen some of the time because
3236
+ // x_top and x_bottom can be extrapolated at the top & bottom of
3237
+ // the shape and actually lie outside the bounding box
3181
3238
  int x;
3182
3239
  for (x=0; x < len; ++x) {
3183
3240
  // cases:
@@ -4414,15 +4471,14 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
4414
4471
  float y_frac;
4415
4472
  int winding = 0;
4416
4473
 
4417
- orig[0] = x;
4418
- orig[1] = y;
4419
-
4420
4474
  // make sure y never passes through a vertex of the shape
4421
4475
  y_frac = (float) STBTT_fmod(y, 1.0f);
4422
4476
  if (y_frac < 0.01f)
4423
4477
  y += 0.01f;
4424
4478
  else if (y_frac > 0.99f)
4425
4479
  y -= 0.01f;
4480
+
4481
+ orig[0] = x;
4426
4482
  orig[1] = y;
4427
4483
 
4428
4484
  // test a ray from (-infinity,y) to (x,y)
@@ -4484,35 +4540,35 @@ static float stbtt__cuberoot( float x )
4484
4540
  return (float) STBTT_pow( x,1.0f/3.0f);
4485
4541
  }
4486
4542
 
4487
- // x^3 + c*x^2 + b*x + a = 0
4543
+ // x^3 + a*x^2 + b*x + c = 0
4488
4544
  static int stbtt__solve_cubic(float a, float b, float c, float* r)
4489
4545
  {
4490
- float s = -a / 3;
4491
- float p = b - a*a / 3;
4492
- float q = a * (2*a*a - 9*b) / 27 + c;
4546
+ float s = -a / 3;
4547
+ float p = b - a*a / 3;
4548
+ float q = a * (2*a*a - 9*b) / 27 + c;
4493
4549
  float p3 = p*p*p;
4494
- float d = q*q + 4*p3 / 27;
4495
- if (d >= 0) {
4496
- float z = (float) STBTT_sqrt(d);
4497
- float u = (-q + z) / 2;
4498
- float v = (-q - z) / 2;
4499
- u = stbtt__cuberoot(u);
4500
- v = stbtt__cuberoot(v);
4501
- r[0] = s + u + v;
4502
- return 1;
4503
- } else {
4504
- float u = (float) STBTT_sqrt(-p/3);
4505
- float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
4506
- float m = (float) STBTT_cos(v);
4550
+ float d = q*q + 4*p3 / 27;
4551
+ if (d >= 0) {
4552
+ float z = (float) STBTT_sqrt(d);
4553
+ float u = (-q + z) / 2;
4554
+ float v = (-q - z) / 2;
4555
+ u = stbtt__cuberoot(u);
4556
+ v = stbtt__cuberoot(v);
4557
+ r[0] = s + u + v;
4558
+ return 1;
4559
+ } else {
4560
+ float u = (float) STBTT_sqrt(-p/3);
4561
+ float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
4562
+ float m = (float) STBTT_cos(v);
4507
4563
  float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
4508
- r[0] = s + u * 2 * m;
4509
- r[1] = s - u * (m + n);
4510
- r[2] = s - u * (m - n);
4564
+ r[0] = s + u * 2 * m;
4565
+ r[1] = s - u * (m + n);
4566
+ r[2] = s - u * (m - n);
4511
4567
 
4512
4568
  //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?
4513
4569
  //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
4514
4570
  //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
4515
- return 3;
4571
+ return 3;
4516
4572
  }
4517
4573
  }
4518
4574
 
@@ -4589,18 +4645,17 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
4589
4645
  for (i=0; i < num_verts; ++i) {
4590
4646
  float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
4591
4647
 
4592
- // 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
4593
- float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4594
- if (dist2 < min_dist*min_dist)
4595
- min_dist = (float) STBTT_sqrt(dist2);
4596
-
4597
- if (verts[i].type == STBTT_vline) {
4648
+ if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
4598
4649
  float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
4599
4650
 
4651
+ float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4652
+ if (dist2 < min_dist*min_dist)
4653
+ min_dist = (float) STBTT_sqrt(dist2);
4654
+
4600
4655
  // coarse culling against bbox
4601
4656
  //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
4602
4657
  // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
4603
- float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
4658
+ dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
4604
4659
  STBTT_assert(i != 0);
4605
4660
  if (dist < min_dist) {
4606
4661
  // check position along line
@@ -4627,7 +4682,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
4627
4682
  float ax = x1-x0, ay = y1-y0;
4628
4683
  float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
4629
4684
  float mx = x0 - sx, my = y0 - sy;
4630
- float res[3],px,py,t,it;
4685
+ float res[3] = {0.f,0.f,0.f};
4686
+ float px,py,t,it,dist2;
4631
4687
  float a_inv = precompute[i];
4632
4688
  if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
4633
4689
  float a = 3*(ax*bx + ay*by);
@@ -4654,6 +4710,10 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
4654
4710
  float d = (mx*ax+my*ay) * a_inv;
4655
4711
  num = stbtt__solve_cubic(b, c, d, res);
4656
4712
  }
4713
+ dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
4714
+ if (dist2 < min_dist*min_dist)
4715
+ min_dist = (float) STBTT_sqrt(dist2);
4716
+
4657
4717
  if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
4658
4718
  t = res[0], it = 1.0f - t;
4659
4719
  px = it*it*x0 + 2*t*it*x1 + t*t*x2;
@@ -4913,6 +4973,12 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
4913
4973
 
4914
4974
  // FULL VERSION HISTORY
4915
4975
  //
4976
+ // 1.25 (2021-07-11) many fixes
4977
+ // 1.24 (2020-02-05) fix warning
4978
+ // 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
4979
+ // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
4980
+ // 1.21 (2019-02-25) fix warning
4981
+ // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
4916
4982
  // 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
4917
4983
  // 1.18 (2018-01-29) add missing function
4918
4984
  // 1.17 (2017-07-23) make more arguments const; doc fix