gosu 1.4.1 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/dependencies/SDL_sound/SDL_sound.c +21 -63
- data/dependencies/SDL_sound/SDL_sound.h +2 -2
- data/dependencies/SDL_sound/SDL_sound_aiff.c +26 -23
- data/dependencies/SDL_sound/SDL_sound_au.c +8 -8
- data/dependencies/SDL_sound/SDL_sound_coreaudio.c +4 -5
- data/dependencies/SDL_sound/SDL_sound_flac.c +28 -30
- data/dependencies/SDL_sound/SDL_sound_internal.h +4 -4
- data/dependencies/SDL_sound/SDL_sound_modplug.c +1 -1
- data/dependencies/SDL_sound/SDL_sound_mp3.c +19 -23
- data/dependencies/SDL_sound/SDL_sound_raw.c +5 -6
- data/dependencies/SDL_sound/SDL_sound_shn.c +4 -4
- data/dependencies/SDL_sound/SDL_sound_voc.c +15 -15
- data/dependencies/SDL_sound/SDL_sound_vorbis.c +14 -7
- data/dependencies/SDL_sound/SDL_sound_wav.c +17 -17
- data/dependencies/SDL_sound/dr_flac.h +10840 -4779
- data/dependencies/SDL_sound/dr_mp3.h +2793 -1004
- data/dependencies/SDL_sound/libmodplug/fastmix.c +5 -0
- data/dependencies/SDL_sound/libmodplug/load_669.c +1 -1
- data/dependencies/SDL_sound/libmodplug/load_amf.c +1 -0
- data/dependencies/SDL_sound/libmodplug/load_ams.c +38 -22
- data/dependencies/SDL_sound/libmodplug/load_it.c +18 -14
- data/dependencies/SDL_sound/libmodplug/load_mdl.c +18 -9
- data/dependencies/SDL_sound/libmodplug/load_med.c +7 -6
- data/dependencies/SDL_sound/libmodplug/load_mt2.c +36 -17
- data/dependencies/SDL_sound/libmodplug/load_okt.c +51 -24
- data/dependencies/SDL_sound/libmodplug/load_psm.c +4 -2
- data/dependencies/SDL_sound/libmodplug/load_s3m.c +4 -4
- data/dependencies/SDL_sound/libmodplug/load_ult.c +4 -3
- data/dependencies/SDL_sound/libmodplug/load_xm.c +5 -5
- data/dependencies/SDL_sound/libmodplug/snd_fx.c +8 -1
- data/dependencies/SDL_sound/libmodplug/sndfile.c +21 -4
- data/dependencies/SDL_sound/stb_vorbis.h +10 -18
- data/dependencies/mojoAL/mojoal.c +260 -6
- data/dependencies/stb/stb_image.h +208 -73
- data/dependencies/stb/stb_image_write.h +57 -23
- data/dependencies/stb/stb_truetype.h +345 -279
- data/dependencies/utf8proc/utf8proc.c +37 -18
- data/dependencies/utf8proc/utf8proc.h +17 -5
- data/dependencies/utf8proc/utf8proc_data.h +12012 -10089
- data/ext/gosu/extconf.rb +6 -3
- data/include/Gosu/Buttons.hpp +103 -103
- data/include/Gosu/Directories.hpp +31 -24
- data/include/Gosu/Font.hpp +4 -2
- data/include/Gosu/Gosu.hpp +5 -8
- data/include/Gosu/IO.hpp +0 -3
- data/include/Gosu/Input.hpp +7 -1
- data/include/Gosu/Math.hpp +0 -3
- data/include/Gosu/TextInput.hpp +3 -3
- data/include/Gosu/Timing.hpp +3 -6
- data/include/Gosu/Version.hpp +1 -1
- data/include/Gosu/Window.hpp +3 -2
- data/rdoc/gosu.rb +16 -2
- data/src/Audio.cpp +2 -2
- data/src/AudioFileAudioToolbox.cpp +1 -1
- data/src/AudioFileSDLSound.cpp +1 -1
- data/src/AudioImpl.cpp +0 -7
- data/src/AudioImpl.hpp +1 -3
- data/src/BitmapIO.cpp +23 -2
- data/src/BlockAllocator.cpp +1 -1
- data/src/DirectoriesApple.cpp +25 -24
- data/src/DirectoriesUnix.cpp +14 -12
- data/src/DirectoriesWin.cpp +26 -30
- data/src/FileUnix.cpp +1 -1
- data/src/FileWin.cpp +1 -1
- data/src/Font.cpp +13 -3
- data/src/Graphics.cpp +1 -1
- data/src/Image.cpp +10 -15
- data/src/Input.cpp +16 -1
- data/src/InputUIKit.cpp +1 -1
- data/src/Macro.cpp +1 -1
- data/src/RubyGosu.cxx +76 -34
- data/src/TextInput.cpp +1 -1
- data/src/TimingApple.cpp +2 -2
- data/src/TimingUnix.cpp +3 -7
- data/src/TimingWin.cpp +1 -2
- data/src/TrueTypeFont.cpp +1 -1
- data/src/Window.cpp +5 -4
- data/src/WindowUIKit.cpp +1 -1
- metadata +3 -3
@@ -1,5 +1,5 @@
|
|
1
|
-
// stb_truetype.h - v1.
|
2
|
-
// authored from 2009-
|
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.
|
308
|
-
glTexCoord2f(q.s1,q.
|
309
|
-
glTexCoord2f(q.s1,q.
|
310
|
-
glTexCoord2f(q.s0,q.
|
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
|
-
|
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
|
-
//
|
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 &&
|
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
|
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
|
2385
|
-
{
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2397
|
-
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
|
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
|
-
|
2409
|
-
|
2410
|
-
|
2411
|
-
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2415
|
-
|
2416
|
-
|
2417
|
-
|
2418
|
-
|
2419
|
-
|
2420
|
-
|
2421
|
-
|
2422
|
-
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
2426
|
-
|
2427
|
-
|
2428
|
-
|
2429
|
-
|
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
|
-
|
2437
|
+
}
|
2438
|
+
break;
|
2439
|
+
}
|
2433
2440
|
|
2434
|
-
|
2435
|
-
|
2436
|
-
STBTT_assert(0);
|
2437
|
-
} break;
|
2438
|
-
}
|
2441
|
+
default: return -1; // unsupported
|
2442
|
+
}
|
2439
2443
|
|
2440
|
-
|
2444
|
+
return -1;
|
2441
2445
|
}
|
2442
2446
|
|
2443
2447
|
static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
2444
2448
|
{
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
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
|
-
|
2481
|
-
|
2457
|
+
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
|
2458
|
+
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
|
2459
|
+
break;
|
2460
|
+
}
|
2482
2461
|
|
2483
|
-
|
2484
|
-
|
2485
|
-
|
2486
|
-
|
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
|
-
|
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
|
2496
|
-
{
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2510
|
-
|
2511
|
-
|
2512
|
-
|
2513
|
-
|
2514
|
-
|
2515
|
-
|
2516
|
-
|
2517
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2528
|
-
|
2529
|
-
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2565
|
-
|
2566
|
-
|
2567
|
-
|
2568
|
-
|
2569
|
-
|
2570
|
-
|
2571
|
-
|
2572
|
-
|
2573
|
-
|
2574
|
-
|
2575
|
-
|
2576
|
-
|
2577
|
-
|
2578
|
-
|
2579
|
-
|
2580
|
-
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
2584
|
-
|
2585
|
-
|
2586
|
-
|
2587
|
-
|
2588
|
-
|
2589
|
-
|
2590
|
-
|
2591
|
-
|
2592
|
-
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
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
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2602
|
+
return 0; // Unsupported position format
|
2603
|
+
}
|
2604
|
+
}
|
2605
|
+
}
|
2619
2606
|
|
2620
|
-
|
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]
|
3135
|
-
scanline_fill[x] +=
|
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)
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 +
|
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
|
-
|
4491
|
-
|
4492
|
-
|
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
|
-
|
4495
|
-
|
4496
|
-
|
4497
|
-
|
4498
|
-
|
4499
|
-
|
4500
|
-
|
4501
|
-
|
4502
|
-
|
4503
|
-
|
4504
|
-
|
4505
|
-
|
4506
|
-
|
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
|
-
|
4509
|
-
|
4510
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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],
|
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
|