Merge pull request #19150 from guilhermefelipecgs/update_stb

Update stb_truetype to 1.19 and stb_vorbis to 1.14
This commit is contained in:
Rémi Verschelde 2018-05-25 12:31:38 +02:00 committed by GitHub
commit 121eaddf11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 542 additions and 242 deletions

View file

@ -342,11 +342,11 @@ Collection of single-file libraries used in Godot components.
* License: zlib * License: zlib
- `stb_truetype.h` - `stb_truetype.h`
* Upstream: https://github.com/nothings/stb * Upstream: https://github.com/nothings/stb
* Version: 1.17 * Version: 1.19
* License: Public Domain (Unlicense) or MIT * License: Public Domain (Unlicense) or MIT
- `stb_vorbis.c` - `stb_vorbis.c`
* Upstream: https://github.com/nothings/stb * Upstream: https://github.com/nothings/stb
* Version: 1.11 * Version: 1.14
* License: Public Domain (Unlicense) or MIT * License: Public Domain (Unlicense) or MIT

View file

@ -1,4 +1,4 @@
// stb_truetype.h - v1.17 - public domain // stb_truetype.h - v1.19 - public domain
// authored from 2009-2016 by Sean Barrett / RAD Game Tools // authored from 2009-2016 by Sean Barrett / RAD Game Tools
// //
// This library processes TrueType files: // This library processes TrueType files:
@ -22,41 +22,35 @@
// Mikko Mononen: compound shape support, more cmap formats // Mikko Mononen: compound shape support, more cmap formats
// Tor Andersson: kerning, subpixel rendering // Tor Andersson: kerning, subpixel rendering
// Dougall Johnson: OpenType / Type 2 font handling // Dougall Johnson: OpenType / Type 2 font handling
// Daniel Ribeiro Maciel: basic GPOS-based kerning
// //
// Misc other: // Misc other:
// Ryan Gordon // Ryan Gordon
// Simon Glass // Simon Glass
// github:IntellectualKitty // github:IntellectualKitty
// Imanol Celaya // Imanol Celaya
// Daniel Ribeiro Maciel
// //
// Bug/warning reports/fixes: // Bug/warning reports/fixes:
// "Zer" on mollyrocket // "Zer" on mollyrocket Fabian "ryg" Giesen
// Cass Everitt // Cass Everitt Martins Mozeiko
// stoiko (Haemimont Games) // stoiko (Haemimont Games) Cap Petschulat
// Brian Hook // Brian Hook Omar Cornut
// Walter van Niftrik // Walter van Niftrik github:aloucks
// David Gow // David Gow Peter LaValle
// David Given // David Given Sergey Popov
// Ivan-Assen Ivanov // Ivan-Assen Ivanov Giumo X. Clanjor
// Anthony Pesch // Anthony Pesch Higor Euripedes
// Johan Duparc // Johan Duparc Thomas Fields
// Hou Qiming // Hou Qiming Derek Vinyard
// Fabian "ryg" Giesen // Rob Loach Cort Stratton
// Martins Mozeiko // Kenney Phillis Jr. github:oyvindjam
// Cap Petschulat // Brian Costabile github:vassvik
// Omar Cornut
// github:aloucks
// Peter LaValle
// Sergey Popov
// Giumo X. Clanjor
// Higor Euripedes
// Thomas Fields
// Derek Vinyard
// Cort Stratton
// github:oyvindjam
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
// 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix // 1.17 (2017-07-23) make more arguments const; doc fix
// 1.16 (2017-07-12) SDF support // 1.16 (2017-07-12) SDF support
// 1.15 (2017-03-03) make more arguments const // 1.15 (2017-03-03) make more arguments const
@ -171,7 +165,7 @@
// measurement for describing font size, defined as 72 points per inch. // measurement for describing font size, defined as 72 points per inch.
// stb_truetype provides a point API for compatibility. However, true // stb_truetype provides a point API for compatibility. However, true
// "per inch" conventions don't make much sense on computer displays // "per inch" conventions don't make much sense on computer displays
// since they different monitors have different number of pixels per // since different monitors have different number of pixels per
// inch. For example, Windows traditionally uses a convention that // inch. For example, Windows traditionally uses a convention that
// there are 96 pixels per inch, thus making 'inch' measurements have // there are 96 pixels per inch, thus making 'inch' measurements have
// nothing to do with inches, and thus effectively defining a point to // nothing to do with inches, and thus effectively defining a point to
@ -181,6 +175,39 @@
// for non-commercial fonts, thus making fonts scaled in points // for non-commercial fonts, thus making fonts scaled in points
// according to the TrueType spec incoherently sized in practice. // according to the TrueType spec incoherently sized in practice.
// //
// DETAILED USAGE:
//
// Scale:
// Select how high you want the font to be, in points or pixels.
// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
// a scale factor SF that will be used by all other functions.
//
// Baseline:
// You need to select a y-coordinate that is the baseline of where
// your text will appear. Call GetFontBoundingBox to get the baseline-relative
// bounding box for all characters. SF*-y0 will be the distance in pixels
// that the worst-case character could extend above the baseline, so if
// you want the top edge of characters to appear at the top of the
// screen where y=0, then you would set the baseline to SF*-y0.
//
// Current point:
// Set the current point where the first character will appear. The
// first character could extend left of the current point; this is font
// dependent. You can either choose a current point that is the leftmost
// point and hope, or add some padding, or check the bounding box or
// left-side-bearing of the first character to be displayed and set
// the current point based on that.
//
// Displaying a character:
// Compute the bounding box of the character. It will contain signed values
// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
// then the character should be displayed in the rectangle from
// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
//
// Advancing for the next character:
// Call GlyphHMetrics, and compute 'current_point += SF * advance'.
//
//
// ADVANCED USAGE // ADVANCED USAGE
// //
// Quality: // Quality:
@ -224,7 +251,7 @@
// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
// Bitmap management 100 LOC / // Bitmap management 100 LOC /
// Baked bitmap interface 70 LOC / // Baked bitmap interface 70 LOC /
// Font name matching & access 150 LOC ---- 150 // Font name matching & access 150 LOC ---- 150
// C runtime library abstraction 60 LOC ---- 60 // C runtime library abstraction 60 LOC ---- 60
// //
// //
@ -317,7 +344,7 @@ int main(int argc, char **argv)
} }
return 0; return 0;
} }
#endif #endif
// //
// Output: // Output:
// //
@ -331,9 +358,9 @@ int main(int argc, char **argv)
// :@@. M@M // :@@. M@M
// @@@o@@@@ // @@@o@@@@
// :M@@V:@@. // :M@@V:@@.
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// Complete program: print "Hello World!" banner, with bugs // Complete program: print "Hello World!" banner, with bugs
// //
#if 0 #if 0
@ -387,7 +414,8 @@ int main(int arg, char **argv)
//// INTEGRATION WITH YOUR CODEBASE //// INTEGRATION WITH YOUR CODEBASE
//// ////
//// The following sections allow you to supply alternate definitions //// The following sections allow you to supply alternate definitions
//// of C library functions used by stb_truetype. //// of C library functions used by stb_truetype, e.g. if you don't
//// link with the C runtime library.
#ifdef STB_TRUETYPE_IMPLEMENTATION #ifdef STB_TRUETYPE_IMPLEMENTATION
// #define your own (u)stbtt_int8/16/32 before including to override this // #define your own (u)stbtt_int8/16/32 before including to override this
@ -403,7 +431,7 @@ int main(int arg, char **argv)
typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
// #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
#ifndef STBTT_ifloor #ifndef STBTT_ifloor
#include <math.h> #include <math.h>
#define STBTT_ifloor(x) ((int) floor(x)) #define STBTT_ifloor(x) ((int) floor(x))
@ -416,6 +444,11 @@ int main(int arg, char **argv)
#define STBTT_pow(x,y) pow(x,y) #define STBTT_pow(x,y) pow(x,y)
#endif #endif
#ifndef STBTT_fmod
#include <math.h>
#define STBTT_fmod(x,y) fmod(x,y)
#endif
#ifndef STBTT_cos #ifndef STBTT_cos
#include <math.h> #include <math.h>
#define STBTT_cos(x) cos(x) #define STBTT_cos(x) cos(x)
@ -427,11 +460,6 @@ int main(int arg, char **argv)
#define STBTT_fabs(x) fabs(x) #define STBTT_fabs(x) fabs(x)
#endif #endif
#ifndef STBTT_fabs
#include <math.h>
#define STBTT_fabs(x) fabs(x)
#endif
// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
#ifndef STBTT_malloc #ifndef STBTT_malloc
#include <stdlib.h> #include <stdlib.h>
@ -625,7 +653,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, cons
// Calling these functions in sequence is roughly equivalent to calling // Calling these functions in sequence is roughly equivalent to calling
// stbtt_PackFontRanges(). If you more control over the packing of multiple // stbtt_PackFontRanges(). If you more control over the packing of multiple
// fonts, or if you want to pack custom data into a font texture, take a look // fonts, or if you want to pack custom data into a font texture, take a look
// at the source to of stbtt_PackFontRanges() and create a custom version // at the source to of stbtt_PackFontRanges() and create a custom version
// using these functions, e.g. call GatherRects multiple times, // using these functions, e.g. call GatherRects multiple times,
// building up a single array of rects, then call PackRects once, // building up a single array of rects, then call PackRects once,
// then call RenderIntoRects repeatedly. This may result in a // then call RenderIntoRects repeatedly. This may result in a
@ -676,7 +704,7 @@ struct stbtt_fontinfo
int numGlyphs; // number of glyphs, needed for range checking int numGlyphs; // number of glyphs, needed for range checking
int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph int indexToLocFormat; // format needed to map from glyph index to glyph
@ -931,7 +959,7 @@ STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, floa
// and computing from that can allow drop-out prevention). // and computing from that can allow drop-out prevention).
// //
// The algorithm has not been optimized at all, so expect it to be slow // The algorithm has not been optimized at all, so expect it to be slow
// if computing lots of characters or very large sizes. // if computing lots of characters or very large sizes.
@ -1319,6 +1347,7 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
info->kern = stbtt__find_table(data, fontstart, "kern"); // not required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
if (!cmap || !info->head || !info->hhea || !info->hmtx) if (!cmap || !info->head || !info->hhea || !info->hmtx)
return 0; return 0;
@ -1687,7 +1716,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
if (i != 0) if (i != 0)
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
// now start the new one // now start the new one
start_off = !(flags & 1); start_off = !(flags & 1);
if (start_off) { if (start_off) {
// if we start off with an off-curve point, then when we need to find a point on the curve // if we start off with an off-curve point, then when we need to find a point on the curve
@ -1740,7 +1769,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
int comp_num_verts = 0, i; int comp_num_verts = 0, i;
stbtt_vertex *comp_verts = 0, *tmp = 0; stbtt_vertex *comp_verts = 0, *tmp = 0;
float mtx[6] = {1,0,0,1,0,0}, m, n; float mtx[6] = {1,0,0,1,0,0}, m, n;
flags = ttSHORT(comp); comp+=2; flags = ttSHORT(comp); comp+=2;
gidx = ttSHORT(comp); comp+=2; gidx = ttSHORT(comp); comp+=2;
@ -1770,7 +1799,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
} }
// Find transformation scales. // Find transformation scales.
m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
@ -2172,7 +2201,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
// push immediate // push immediate
if (b0 == 255) { if (b0 == 255) {
f = (float)stbtt__buf_get32(&b) / 0x10000; f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
} else { } else {
stbtt__buf_skip(&b, -1); stbtt__buf_skip(&b, -1);
f = (float)(stbtt_int16)stbtt__cff_int(&b); f = (float)(stbtt_int16)stbtt__cff_int(&b);
@ -2210,12 +2239,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in
{ {
stbtt__csctx c = STBTT__CSCTX_INIT(1); stbtt__csctx c = STBTT__CSCTX_INIT(1);
int r = stbtt__run_charstring(info, glyph_index, &c); int r = stbtt__run_charstring(info, glyph_index, &c);
if (x0) { if (x0) *x0 = r ? c.min_x : 0;
*x0 = r ? c.min_x : 0; if (y0) *y0 = r ? c.min_y : 0;
*y0 = r ? c.min_y : 0; if (x1) *x1 = r ? c.max_x : 0;
*x1 = r ? c.max_x : 0; if (y1) *y1 = r ? c.max_y : 0;
*y1 = r ? c.max_y : 0;
}
return r ? c.num_vertices : 0; return r ? c.num_vertices : 0;
} }
@ -2239,7 +2266,7 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
} }
} }
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{ {
stbtt_uint8 *data = info->data + info->kern; stbtt_uint8 *data = info->data + info->kern;
stbtt_uint32 needle, straw; stbtt_uint32 needle, straw;
@ -2269,9 +2296,260 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
return 0; return 0;
} }
static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
{
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
switch(coverageFormat) {
case 1: {
stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
// Binary search.
stbtt_int32 l=0, r=glyphCount-1, m;
int straw, needle=glyph;
while (l <= r) {
stbtt_uint8 *glyphArray = coverageTable + 4;
stbtt_uint16 glyphID;
m = (l + r) >> 1;
glyphID = ttUSHORT(glyphArray + 2 * m);
straw = glyphID;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
return m;
}
}
} break;
case 2: {
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
stbtt_uint8 *rangeArray = coverageTable + 4;
// Binary search.
stbtt_int32 l=0, r=rangeCount-1, m;
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
stbtt_uint8 *rangeRecord;
m = (l + r) >> 1;
rangeRecord = rangeArray + 6 * m;
strawStart = ttUSHORT(rangeRecord);
strawEnd = ttUSHORT(rangeRecord + 2);
if (needle < strawStart)
r = m - 1;
else if (needle > strawEnd)
l = m + 1;
else {
stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
return startCoverageIndex + glyph - strawStart;
}
}
} break;
default: {
// There are no other cases.
STBTT_assert(0);
} break;
}
return -1;
}
static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
{
stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
switch(classDefFormat)
{
case 1: {
stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
classDefTable = classDef1ValueArray + 2 * glyphCount;
} break;
case 2: {
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
stbtt_uint8 *classRangeRecords = classDefTable + 4;
// Binary search.
stbtt_int32 l=0, r=classRangeCount-1, m;
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
stbtt_uint8 *classRangeRecord;
m = (l + r) >> 1;
classRangeRecord = classRangeRecords + 6 * m;
strawStart = ttUSHORT(classRangeRecord);
strawEnd = ttUSHORT(classRangeRecord + 2);
if (needle < strawStart)
r = m - 1;
else if (needle > strawEnd)
l = m + 1;
else
return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
}
classDefTable = classRangeRecords + 6 * classRangeCount;
} break;
default: {
// There are no other cases.
STBTT_assert(0);
} break;
}
return -1;
}
// Define to STBTT_assert(x) if you want to break on unimplemented formats.
#define STBTT_GPOS_TODO_assert(x)
static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{
stbtt_uint16 lookupListOffset;
stbtt_uint8 *lookupList;
stbtt_uint16 lookupCount;
stbtt_uint8 *data;
stbtt_int32 i;
if (!info->gpos) return 0;
data = info->data + info->gpos;
if (ttUSHORT(data+0) != 1) return 0; // Major version 1
if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
lookupListOffset = ttUSHORT(data+8);
lookupList = data + lookupListOffset;
lookupCount = ttUSHORT(lookupList);
for (i=0; i<lookupCount; ++i) {
stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
stbtt_uint8 *lookupTable = lookupList + lookupOffset;
stbtt_uint16 lookupType = ttUSHORT(lookupTable);
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
stbtt_uint8 *subTableOffsets = lookupTable + 6;
switch(lookupType) {
case 2: { // Pair Adjustment Positioning Subtable
stbtt_int32 sti;
for (sti=0; sti<subTableCount; sti++) {
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
stbtt_uint8 *table = lookupTable + subtableOffset;
stbtt_uint16 posFormat = ttUSHORT(table);
stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
if (coverageIndex == -1) continue;
switch (posFormat) {
case 1: {
stbtt_int32 l, r, m;
int straw, needle;
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
stbtt_int32 valueRecordPairSizeInBytes = 2;
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
stbtt_uint8 *pairValueTable = table + pairPosOffset;
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
stbtt_uint8 *pairValueArray = pairValueTable + 2;
// TODO: Support more formats.
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
if (valueFormat1 != 4) return 0;
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
if (valueFormat2 != 0) return 0;
STBTT_assert(coverageIndex < pairSetCount);
needle=glyph2;
r=pairValueCount-1;
l=0;
// Binary search.
while (l <= r) {
stbtt_uint16 secondGlyph;
stbtt_uint8 *pairValue;
m = (l + r) >> 1;
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
secondGlyph = ttUSHORT(pairValue);
straw = secondGlyph;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
return xAdvance;
}
}
} break;
case 2: {
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
stbtt_uint16 class1Count = ttUSHORT(table + 12);
stbtt_uint16 class2Count = ttUSHORT(table + 14);
STBTT_assert(glyph1class < class1Count);
STBTT_assert(glyph2class < class2Count);
// TODO: Support more formats.
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
if (valueFormat1 != 4) return 0;
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
if (valueFormat2 != 0) return 0;
if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
stbtt_uint8 *class1Records = table + 16;
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
return xAdvance;
}
} break;
default: {
// There are no other cases.
STBTT_assert(0);
break;
};
}
}
break;
};
default:
// TODO: Implement other stuff.
break;
}
}
return 0;
}
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
{
int xAdvance = 0;
if (info->gpos)
xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
if (info->kern)
xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
return xAdvance;
}
STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
{ {
if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
return 0; return 0;
return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
} }
@ -2395,7 +2673,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
hh->num_remaining_in_head_chunk = count; hh->num_remaining_in_head_chunk = count;
} }
--hh->num_remaining_in_head_chunk; --hh->num_remaining_in_head_chunk;
return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
} }
} }
@ -2449,7 +2727,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
STBTT_assert(z != NULL); STBTT_assert(z != NULL);
if (!z) return z; if (!z) return z;
// round dx down to avoid overshooting // round dx down to avoid overshooting
if (dxdy < 0) if (dxdy < 0)
z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
@ -2527,7 +2805,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
} }
} }
} }
e = e->next; e = e->next;
} }
} }
@ -3229,8 +3507,9 @@ error:
STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
{ {
float scale = scale_x > scale_y ? scale_y : scale_x; float scale = scale_x > scale_y ? scale_y : scale_x;
int winding_count, *winding_lengths; int winding_count = 0;
int *winding_lengths = NULL;
stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
if (windings) { if (windings) {
stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
@ -3248,7 +3527,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
{ {
int ix0,iy0,ix1,iy1; int ix0,iy0,ix1,iy1;
stbtt__bitmap gbm; stbtt__bitmap gbm;
stbtt_vertex *vertices; stbtt_vertex *vertices;
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
if (scale_x == 0) scale_x = scale_y; if (scale_x == 0) scale_x = scale_y;
@ -3271,7 +3550,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
if (height) *height = gbm.h; if (height) *height = gbm.h;
if (xoff ) *xoff = ix0; if (xoff ) *xoff = ix0;
if (yoff ) *yoff = iy0; if (yoff ) *yoff = iy0;
if (gbm.w && gbm.h) { if (gbm.w && gbm.h) {
gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
if (gbm.pixels) { if (gbm.pixels) {
@ -3282,7 +3561,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
} }
STBTT_free(vertices, info->userdata); STBTT_free(vertices, info->userdata);
return gbm.pixels; return gbm.pixels;
} }
STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
{ {
@ -3294,7 +3573,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne
int ix0,iy0; int ix0,iy0;
stbtt_vertex *vertices; stbtt_vertex *vertices;
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
stbtt__bitmap gbm; stbtt__bitmap gbm;
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
gbm.pixels = output; gbm.pixels = output;
@ -3316,7 +3595,12 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *
STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
{ {
return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
} }
STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
{
stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
}
STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
{ {
@ -3326,7 +3610,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns
STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
{ {
return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
} }
STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
{ {
@ -3451,7 +3735,7 @@ static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *no
con->y = 0; con->y = 0;
con->bottom_y = 0; con->bottom_y = 0;
STBTT__NOTUSED(nodes); STBTT__NOTUSED(nodes);
STBTT__NOTUSED(num_nodes); STBTT__NOTUSED(num_nodes);
} }
static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
@ -3826,7 +4110,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char
n = 0; n = 0;
for (i=0; i < num_ranges; ++i) for (i=0; i < num_ranges; ++i)
n += ranges[i].num_chars; n += ranges[i].num_chars;
rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
if (rects == NULL) if (rects == NULL)
return 0; return 0;
@ -3837,7 +4121,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char
n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
stbtt_PackFontRangesPackRects(spc, rects, n); stbtt_PackFontRangesPackRects(spc, rects, n);
return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
STBTT_free(rects, spc->user_allocator_context); STBTT_free(rects, spc->user_allocator_context);
@ -3909,7 +4193,7 @@ static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2],
float discr = b*b - a*c; float discr = b*b - a*c;
if (discr > 0.0) { if (discr > 0.0) {
float rcpna = -1 / a; float rcpna = -1 / a;
float d = (float) sqrt(discr); float d = (float) STBTT_sqrt(discr);
s0 = (b+d) * rcpna; s0 = (b+d) * rcpna;
s1 = (b-d) * rcpna; s1 = (b-d) * rcpna;
if (s0 >= 0.0 && s0 <= 1.0) if (s0 >= 0.0 && s0 <= 1.0)
@ -3971,7 +4255,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
orig[1] = y; orig[1] = y;
// make sure y never passes through a vertex of the shape // make sure y never passes through a vertex of the shape
y_frac = (float) fmod(y, 1.0f); y_frac = (float) STBTT_fmod(y, 1.0f);
if (y_frac < 0.01f) if (y_frac < 0.01f)
y += 0.01f; y += 0.01f;
else if (y_frac > 0.99f) else if (y_frac > 0.99f)
@ -3985,7 +4269,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
if (x_inter < x) if (x_inter < x)
winding += (y0 < y1) ? 1 : -1; winding += (y0 < y1) ? 1 : -1;
} }
} }
@ -4011,7 +4295,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
y1 = (int)verts[i ].y; y1 = (int)verts[i ].y;
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
if (x_inter < x) if (x_inter < x)
winding += (y0 < y1) ? 1 : -1; winding += (y0 < y1) ? 1 : -1;
} }
} else { } else {
@ -4023,7 +4307,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
if (hits[1][0] < 0) if (hits[1][0] < 0)
winding += (hits[1][1] < 0 ? -1 : 1); winding += (hits[1][1] < 0 ? -1 : 1);
} }
} }
} }
} }
return winding; return winding;
@ -4104,7 +4388,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
// invert for y-downwards bitmaps // invert for y-downwards bitmaps
scale_y = -scale_y; scale_y = -scale_y;
{ {
int x,y,i,j; int x,y,i,j;
float *precompute; float *precompute;
@ -4253,7 +4537,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
STBTT_free(verts, info->userdata); STBTT_free(verts, info->userdata);
} }
return data; return data;
} }
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
{ {
@ -4271,7 +4555,7 @@ STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
// //
// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
{ {
stbtt_int32 i=0; stbtt_int32 i=0;
@ -4310,7 +4594,7 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, s
return i; return i;
} }
static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
{ {
return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
} }
@ -4439,7 +4723,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
{ {
return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
} }
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
@ -4471,6 +4755,9 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
// FULL VERSION HISTORY // FULL VERSION HISTORY
// //
// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
// 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix
// 1.16 (2017-07-12) SDF support // 1.16 (2017-07-12) SDF support
// 1.15 (2017-03-03) make more arguments const // 1.15 (2017-03-03) make more arguments const
// 1.14 (2017-01-16) num-fonts-in-TTC function // 1.14 (2017-01-16) num-fonts-in-TTC function
@ -4529,38 +4816,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE A - MIT License ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org) ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose, software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means. commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law. this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*/ */

View file

@ -1,11 +1,11 @@
// Ogg Vorbis audio decoder - v1.11 - public domain // Ogg Vorbis audio decoder - v1.14 - public domain
// http://nothings.org/stb_vorbis/ // http://nothings.org/stb_vorbis/
// //
// Original version written by Sean Barrett in 2007. // Original version written by Sean Barrett in 2007.
// //
// Originally sponsored by RAD Game Tools. Seeking sponsored // Originally sponsored by RAD Game Tools. Seeking implementation
// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software, // sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker,
// Aras Pranckevicius, and Sean Barrett. // Elias Software, Aras Pranckevicius, and Sean Barrett.
// //
// LICENSE // LICENSE
// //
@ -30,22 +30,26 @@
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart // Phillip Bennefall Rohit Thiago Goulart
// manxorist@github saga musix github:infatum // manxorist@github saga musix github:infatum
// Timur Gagiev
// //
// Partial history: // Partial history:
// 1.11 - 2017/07/23 - fix MinGW compilation // 1.14 - 2018-02-11 - delete bogus dealloca usage
// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory // 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version // 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame // 1.11 - 2017-07-23 - fix MinGW compilation
// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const // 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory
// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) // 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version
// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame
// 1.07 - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const
// 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)
// some crash fixes when out of memory or with corrupt files // some crash fixes when out of memory or with corrupt files
// fix some inappropriately signed shifts // fix some inappropriately signed shifts
// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant // 1.05 - 2015-04-19 - don't define __forceinline if it's redundant
// 1.04 - 2014/08/27 - fix missing const-correct case in API // 1.04 - 2014-08-27 - fix missing const-correct case in API
// 1.03 - 2014/08/07 - warning fixes // 1.03 - 2014-08-07 - warning fixes
// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows // 1.02 - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows
// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct) // 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct)
// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel; // 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
// (API change) report sample rate for decode-full-file funcs // (API change) report sample rate for decode-full-file funcs
// //
// See end of file for full version history. // See end of file for full version history.
@ -816,7 +820,7 @@ struct stb_vorbis
int current_loc_valid; int current_loc_valid;
// per-blocksize precomputed data // per-blocksize precomputed data
// twiddle factors // twiddle factors
float *A[2],*B[2],*C[2]; float *A[2],*B[2],*C[2];
float *window[2]; float *window[2];
@ -880,11 +884,7 @@ static int error(vorb *f, enum STBVorbisError e)
#define array_size_required(count,size) (count*(sizeof(void *)+(size))) #define array_size_required(count,size) (count*(sizeof(void *)+(size)))
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) #define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))
#ifdef dealloca
#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size))
#else
#define temp_free(f,p) 0 #define temp_free(f,p) 0
#endif
#define temp_alloc_save(f) ((f)->temp_offset) #define temp_alloc_save(f) ((f)->temp_offset)
#define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) #define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
@ -1142,7 +1142,7 @@ static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values)
if (!c->sparse) { if (!c->sparse) {
int k = 0; int k = 0;
for (i=0; i < c->entries; ++i) for (i=0; i < c->entries; ++i)
if (include_in_sort(c, lengths[i])) if (include_in_sort(c, lengths[i]))
c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); c->sorted_codewords[k++] = bit_reverse(c->codewords[i]);
assert(k == c->sorted_entries); assert(k == c->sorted_entries);
} else { } else {
@ -1323,7 +1323,7 @@ static int getn(vorb *z, uint8 *data, int n)
return 1; return 1;
} }
#ifndef STB_VORBIS_NO_STDIO #ifndef STB_VORBIS_NO_STDIO
if (fread(data, n, 1, z->f) == 1) if (fread(data, n, 1, z->f) == 1)
return 1; return 1;
else { else {
@ -1403,7 +1403,7 @@ static int start_page_no_capturepattern(vorb *f)
// header flag // header flag
f->page_flag = get8(f); f->page_flag = get8(f);
// absolute granule position // absolute granule position
loc0 = get32(f); loc0 = get32(f);
loc1 = get32(f); loc1 = get32(f);
// @TODO: validate loc0,loc1 as valid positions? // @TODO: validate loc0,loc1 as valid positions?
// stream serial number -- vorbis doesn't interleave, so discard // stream serial number -- vorbis doesn't interleave, so discard
@ -1888,69 +1888,69 @@ static int predict_point(int x, int x0, int x1, int y0, int y1)
// the following table is block-copied from the specification // the following table is block-copied from the specification
static float inverse_db_table[256] = static float inverse_db_table[256] =
{ {
1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f,
1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f,
1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f,
2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f,
2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f,
3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f,
4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f,
6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f,
7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f,
1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f,
1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f,
1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f,
2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f,
2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f,
3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f,
4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f,
5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f,
7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f,
9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f,
1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f,
1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f,
2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f,
2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f,
3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f,
4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f,
5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f,
7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f,
9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f,
0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f,
0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f,
0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f,
0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f,
0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f,
0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f,
0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f,
0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f,
0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f,
0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f,
0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f,
0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f,
0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f,
0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f,
0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f,
0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f,
0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f,
0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f,
0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f,
0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f,
0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f,
0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f,
0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f,
0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f,
0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f,
0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f,
0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f,
0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f,
0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f,
0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f,
0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f,
0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f,
0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f,
0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f,
0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f,
0.82788260f, 0.88168307f, 0.9389798f, 1.0f 0.82788260f, 0.88168307f, 0.9389798f, 1.0f
}; };
@ -2042,6 +2042,8 @@ static int residue_decode(vorb *f, Codebook *book, float *target, int offset, in
return TRUE; return TRUE;
} }
// n is 1/2 of the blocksize --
// specification: "Correct per-vector decode length is [n]/2"
static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode)
{ {
int i,j,pass; int i,j,pass;
@ -2049,7 +2051,10 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
int rtype = f->residue_types[rn]; int rtype = f->residue_types[rn];
int c = r->classbook; int c = r->classbook;
int classwords = f->codebooks[c].dimensions; int classwords = f->codebooks[c].dimensions;
int n_read = r->end - r->begin; unsigned int actual_size = rtype == 2 ? n*2 : n;
unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size);
unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size);
int n_read = limit_r_end - limit_r_begin;
int part_read = n_read / r->part_size; int part_read = n_read / r->part_size;
int temp_alloc_point = temp_alloc_save(f); int temp_alloc_point = temp_alloc_save(f);
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
@ -2346,11 +2351,11 @@ void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)
#if LIBVORBIS_MDCT #if LIBVORBIS_MDCT
// directly call the vorbis MDCT using an interface documented // directly call the vorbis MDCT using an interface documented
// by Jeff Roberts... useful for performance comparison // by Jeff Roberts... useful for performance comparison
typedef struct typedef struct
{ {
int n; int n;
int log2n; int log2n;
float *trig; float *trig;
int *bitrev; int *bitrev;
@ -2369,7 +2374,7 @@ void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
if (M1.n == n) M = &M1; if (M1.n == n) M = &M1;
else if (M2.n == n) M = &M2; else if (M2.n == n) M = &M2;
else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; }
else { else {
if (M2.n) __asm int 3; if (M2.n) __asm int 3;
mdct_init(&M2, n); mdct_init(&M2, n);
M = &M2; M = &M2;
@ -2782,7 +2787,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d1[0] = u[k4+1]; d1[0] = u[k4+1];
d0[1] = u[k4+2]; d0[1] = u[k4+2];
d0[0] = u[k4+3]; d0[0] = u[k4+3];
d0 -= 4; d0 -= 4;
d1 -= 4; d1 -= 4;
bitrev += 2; bitrev += 2;
@ -2863,7 +2868,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
float p0,p1,p2,p3; float p0,p1,p2,p3;
p3 = e[6]*B[7] - e[7]*B[6]; p3 = e[6]*B[7] - e[7]*B[6];
p2 = -e[6]*B[6] - e[7]*B[7]; p2 = -e[6]*B[6] - e[7]*B[7];
d0[0] = p3; d0[0] = p3;
d1[3] = - p3; d1[3] = - p3;
@ -2871,7 +2876,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d3[3] = p2; d3[3] = p2;
p1 = e[4]*B[5] - e[5]*B[4]; p1 = e[4]*B[5] - e[5]*B[4];
p0 = -e[4]*B[4] - e[5]*B[5]; p0 = -e[4]*B[4] - e[5]*B[5];
d0[1] = p1; d0[1] = p1;
d1[2] = - p1; d1[2] = - p1;
@ -2879,7 +2884,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d3[2] = p0; d3[2] = p0;
p3 = e[2]*B[3] - e[3]*B[2]; p3 = e[2]*B[3] - e[3]*B[2];
p2 = -e[2]*B[2] - e[3]*B[3]; p2 = -e[2]*B[2] - e[3]*B[3];
d0[2] = p3; d0[2] = p3;
d1[1] = - p3; d1[1] = - p3;
@ -2887,7 +2892,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d3[1] = p2; d3[1] = p2;
p1 = e[0]*B[1] - e[1]*B[0]; p1 = e[0]*B[1] - e[1]*B[0];
p0 = -e[0]*B[0] - e[1]*B[1]; p0 = -e[0]*B[0] - e[1]*B[1];
d0[3] = p1; d0[3] = p1;
d1[0] = - p1; d1[0] = - p1;
@ -3391,7 +3396,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
if (f->last_seg_which == f->end_seg_with_known_loc) { if (f->last_seg_which == f->end_seg_with_known_loc) {
// if we have a valid current loc, and this is final: // if we have a valid current loc, and this is final:
if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) {
uint32 current_end = f->known_loc_for_packet - (n-right_end); uint32 current_end = f->known_loc_for_packet;
// then let's infer the size of the (probably) short final frame // then let's infer the size of the (probably) short final frame
if (current_end < f->current_loc + (right_end-left_start)) { if (current_end < f->current_loc + (right_end-left_start)) {
if (current_end < f->current_loc) { if (current_end < f->current_loc) {
@ -3400,7 +3405,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
} else { } else {
*len = current_end - f->current_loc; *len = current_end - f->current_loc;
} }
*len += left_start; *len += left_start; // this doesn't seem right, but has no ill effect on my test files
if (*len > right_end) *len = right_end; // this should never happen if (*len > right_end) *len = right_end; // this should never happen
f->current_loc += *len; f->current_loc += *len;
return TRUE; return TRUE;
@ -3521,7 +3526,7 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
first = FALSE; first = FALSE;
} }
for (; s == -1;) { for (; s == -1;) {
uint8 *q; uint8 *q;
int n; int n;
// check that we have the page header ready // check that we have the page header ready
@ -3874,7 +3879,7 @@ static int start_decoder(vorb *f)
} else { } else {
stbv__floor_ordering p[31*8+2]; stbv__floor_ordering p[31*8+2];
Floor1 *g = &f->floor_config[i].floor1; Floor1 *g = &f->floor_config[i].floor1;
int max_class = -1; int max_class = -1;
g->partitions = get_bits(f, 5); g->partitions = get_bits(f, 5);
for (j=0; j < g->partitions; ++j) { for (j=0; j < g->partitions; ++j) {
g->partition_class_list[j] = get_bits(f, 4); g->partition_class_list[j] = get_bits(f, 4);
@ -3984,7 +3989,7 @@ static int start_decoder(vorb *f)
if (f->mapping == NULL) return error(f, VORBIS_outofmem); if (f->mapping == NULL) return error(f, VORBIS_outofmem);
memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));
for (i=0; i < f->mapping_count; ++i) { for (i=0; i < f->mapping_count; ++i) {
Mapping *m = f->mapping + i; Mapping *m = f->mapping + i;
int mapping_type = get_bits(f,16); int mapping_type = get_bits(f,16);
if (mapping_type != 0) return error(f, VORBIS_invalid_setup); if (mapping_type != 0) return error(f, VORBIS_invalid_setup);
m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan));
@ -4050,6 +4055,7 @@ static int start_decoder(vorb *f)
f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist);
if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem); if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem);
memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1);
#ifdef STB_VORBIS_NO_DEFER_FLOOR #ifdef STB_VORBIS_NO_DEFER_FLOOR
f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem); if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem);
@ -4077,7 +4083,10 @@ static int start_decoder(vorb *f)
int i,max_part_read=0; int i,max_part_read=0;
for (i=0; i < f->residue_count; ++i) { for (i=0; i < f->residue_count; ++i) {
Residue *r = f->residue_config + i; Residue *r = f->residue_config + i;
int n_read = r->end - r->begin; unsigned int actual_size = f->blocksize_1 / 2;
unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size;
unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size;
int n_read = limit_r_end - limit_r_begin;
int part_read = n_read / r->part_size; int part_read = n_read / r->part_size;
if (part_read > max_part_read) if (part_read > max_part_read)
max_part_read = part_read; max_part_read = part_read;
@ -4088,6 +4097,8 @@ static int start_decoder(vorb *f)
classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *));
#endif #endif
// maximum reasonable partition size is f->blocksize_1
f->temp_memory_required = classify_mem; f->temp_memory_required = classify_mem;
if (imdct_mem > f->temp_memory_required) if (imdct_mem > f->temp_memory_required)
f->temp_memory_required = imdct_mem; f->temp_memory_required = imdct_mem;
@ -4963,7 +4974,7 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, con
stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)
{ {
FILE *f = fopen(filename, "rb"); FILE *f = fopen(filename, "rb");
if (f) if (f)
return stb_vorbis_open_file(f, TRUE, error, alloc); return stb_vorbis_open_file(f, TRUE, error, alloc);
if (error) *error = VORBIS_file_open_failure; if (error) *error = VORBIS_file_open_failure;
return NULL; return NULL;
@ -5026,7 +5037,7 @@ static int8 channel_position[7][6] =
#define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT))
#define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22))
#define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s))
#define check_endianness() #define check_endianness()
#else #else
#define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s))))
#define check_endianness() #define check_endianness()
@ -5351,20 +5362,22 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
#endif // STB_VORBIS_NO_PULLDATA_API #endif // STB_VORBIS_NO_PULLDATA_API
/* Version history /* Version history
1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version 1.11 - 2017-07-23 - fix MinGW compilation
1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory
1.09 - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version
1.08 - 2016-04-02 - fixed multiple warnings; fix setup memory leaks;
avoid discarding last frame of audio data avoid discarding last frame of audio data
1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API 1.07 - 2015-01-16 - fixed some warnings, fix mingw, const-correct API
some more crash fixes when out of memory or with corrupt files some more crash fixes when out of memory or with corrupt files
1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)
some crash fixes when out of memory or with corrupt files some crash fixes when out of memory or with corrupt files
1.05 - 2015/04/19 - don't define __forceinline if it's redundant 1.05 - 2015-04-19 - don't define __forceinline if it's redundant
1.04 - 2014/08/27 - fix missing const-correct case in API 1.04 - 2014-08-27 - fix missing const-correct case in API
1.03 - 2014/08/07 - Warning fixes 1.03 - 2014-08-07 - Warning fixes
1.02 - 2014/07/09 - Declare qsort compare function _cdecl on windows 1.02 - 2014-07-09 - Declare qsort compare function _cdecl on windows
1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float
1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in multichannel 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel
(API change) report sample rate for decode-full-file funcs (API change) report sample rate for decode-full-file funcs
0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila 0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila
0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem
@ -5412,38 +5425,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE A - MIT License ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org) ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose, software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means. commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law. this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*/ */