More reliable font cache

This commit is contained in:
Jack Andersen 2015-11-29 16:55:08 -10:00
parent 5e7c12ed50
commit 11dfa963b5
2 changed files with 24 additions and 11 deletions

View File

@ -58,7 +58,7 @@ class FontAtlas
{ {
friend class FontCache; friend class FontCache;
FT_Face m_face; FT_Face m_face;
boo::ITextureSA* m_tex; boo::ITextureSA* m_tex = nullptr;
uint32_t m_dpi; uint32_t m_dpi;
FT_Fixed m_ftXscale; FT_Fixed m_ftXscale;
FT_UShort m_ftXPpem; FT_UShort m_ftXPpem;

View File

@ -174,6 +174,8 @@ static void WriteCompressed(Athena::io::FileWriter& writer, const atUint8* data,
z.next_in = (Bytef*)data; z.next_in = (Bytef*)data;
z.avail_in = sz; z.avail_in = sz;
writer.writeUint32Big(sz); writer.writeUint32Big(sz);
atUint64 adlerPos = writer.position();
writer.writeUint32Big(0); /* Space for adler32 */
while (z.avail_in) while (z.avail_in)
{ {
z.next_out = compBuf; z.next_out = compBuf;
@ -191,30 +193,35 @@ static void WriteCompressed(Athena::io::FileWriter& writer, const atUint8* data,
writer.writeUBytes(compBuf, 8192 - z.avail_out); writer.writeUBytes(compBuf, 8192 - z.avail_out);
} }
writer.seek(adlerPos, Athena::Begin);
writer.writeUint32Big(z.adler);
deflateEnd(&z); deflateEnd(&z);
} }
static void ReadDecompressed(Athena::io::FileReader& reader, atUint8* data, size_t sz) static bool ReadDecompressed(Athena::io::FileReader& reader, atUint8* data, size_t sz)
{ {
atUint8 compBuf[8192]; atUint8 compBuf[8192];
z_stream z = {}; z_stream z = {};
inflateInit(&z); inflateInit(&z);
z.next_out = data; z.next_out = data;
atUint32 targetSz = reader.readUint32Big(); atUint32 targetSz = reader.readUint32Big();
atUint32 adler32 = reader.readUint32Big();
z.avail_out = std::min(sz, size_t(targetSz)); z.avail_out = std::min(sz, size_t(targetSz));
size_t readSz; size_t readSz;
while ((readSz = reader.readUBytesToBuf(compBuf, 8192))) while ((readSz = reader.readUBytesToBuf(compBuf, 8192)))
{ {
z.next_in = compBuf; z.next_in = compBuf;
z.avail_in = readSz; z.avail_in = readSz;
inflate(&z, Z_NO_FLUSH); if (inflate(&z, Z_NO_FLUSH) == Z_STREAM_END)
break;
} }
int finishCycle = Z_OK;
while (finishCycle != Z_STREAM_END)
finishCycle = inflate(&z, Z_FINISH);
inflateEnd(&z); inflateEnd(&z);
if (adler32 != z.adler)
return false;
return true;
} }
FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi, FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
@ -537,7 +544,8 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
} }
ReadDecompressed(reader, (atUint8*)texmap.get(), bufSz); if (!ReadDecompressed(reader, (atUint8*)texmap.get(), bufSz))
return;
m_tex = m_tex =
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1, gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
boo::TextureFormat::RGBA8, texmap.get(), bufSz); boo::TextureFormat::RGBA8, texmap.get(), bufSz);
@ -613,7 +621,8 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
charcode = FT_Get_Next_Char(face, charcode, &gindex); charcode = FT_Get_Next_Char(face, charcode, &gindex);
} }
ReadDecompressed(reader, (atUint8*)texmap.get(), bufSz); if (!ReadDecompressed(reader, (atUint8*)texmap.get(), bufSz))
return;
m_tex = m_tex =
gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1, gf->newStaticArrayTexture(TEXMAP_DIM, finalHeight, fullTexmapLayers + 1,
boo::TextureFormat::I8, texmap.get(), bufSz); boo::TextureFormat::I8, texmap.get(), bufSz);
@ -672,11 +681,15 @@ FontTag FontCache::prepCustomFont(boo::IGraphicsDataFactory* gf, const std::stri
atUint32 magic = r.readUint32Big(); atUint32 magic = r.readUint32Big();
if (r.position() == 4 && magic == 'FONT') if (r.position() == 4 && magic == 'FONT')
{ {
m_cachedAtlases.emplace(tag, std::make_unique<FontAtlas>(gf, face, dpi, subpixel, filter, r)); std::unique_ptr<FontAtlas> fa = std::make_unique<FontAtlas>(gf, face, dpi, subpixel, filter, r);
if (fa->m_tex)
{
m_cachedAtlases.emplace(tag, std::move(fa));
return tag; return tag;
} }
} }
} }
}
/* Nada, build and cache now */ /* Nada, build and cache now */
Athena::io::FileWriter w(cachePath); Athena::io::FileWriter w(cachePath);