lsnes/fonts/verifyhexfont.cpp
Ilari Liusvaara c932df0faa lsnes rr0-β0
The first release for public testing.
2011-09-13 17:50:18 +03:00

116 lines
No EOL
3.2 KiB
C++

#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <set>
extern uint32_t fontdata_size;
extern uint32_t fontdata[];
uint32_t mdir_use = 0;
uint32_t mdir_nuse = 0;
uint32_t sdir_gkey = 0;
uint32_t sdir_bkey = 0;
uint32_t ftype0 = 0;
uint32_t ftype1 = 0;
std::set<uint32_t> seen;
//This is Jenkin's MIX function.
uint32_t keyhash(uint32_t key, uint32_t item, uint32_t mod)
{
uint32_t a = key;
uint32_t b = 0;
uint32_t c = item;
a=a-b; a=a-c; a=a^(c >> 13);
b=b-c; b=b-a; b=b^(a << 8);
c=c-a; c=c-b; c=c^(b >> 13);
a=a-b; a=a-c; a=a^(c >> 12);
b=b-c; b=b-a; b=b^(a << 16);
c=c-a; c=c-b; c=c^(b >> 5);
a=a-b; a=a-c; a=a^(c >> 3);
b=b-c; b=b-a; b=b^(a << 10);
c=c-a; c=c-b; c=c^(b >> 15);
return c % mod;
}
void verify_font(uint32_t cp, uint32_t offset)
{
if(offset >= fontdata_size) {
std::cerr << "Font verify error: Bad offset for codepoint " << cp << "." << std::endl;
}
if(seen.count(offset))
return;
if(fontdata[offset] > 1) {
std::cerr << "Font verify error: Bad glyph type for codepoint " << cp << "." << std::endl;
exit(1);
}
if(fontdata[offset] == 0)
ftype0++;
else if(fontdata[offset] == 1)
ftype1++;
seen.insert(offset);
}
void verify_subdirectory(uint32_t offset, uint32_t mseed, uint32_t msize, uint32_t snum)
{
if(offset + 2 > fontdata_size) {
std::cerr << "Font verify error: Subdirectory offset out of range: " << offset << "." << std::endl;
exit(1);
}
uint32_t sseed = fontdata[offset++];
uint32_t ssize = fontdata[offset++];
if(offset + 2 * ssize > fontdata_size) {
std::cerr << "Font verify error: Subdirectory offset out of range: " << offset - 2 << "." << std::endl;
exit(1);
}
if(ssize)
mdir_use++;
else
mdir_nuse++;
for(uint32_t i = 0; i < ssize; i++) {
uint32_t cp = fontdata[offset++];
uint32_t foffset = fontdata[offset++];
if(keyhash(mseed, cp, msize) == snum && keyhash(sseed, cp, ssize) == i) {
verify_font(cp, foffset);
sdir_gkey++;
} else if(foffset != 0) {
std::cerr << "Font verify error: Bad codepoint with nonzero offset: " << i << " of "
<< snum << "." << std::endl;
exit(1);
} else
sdir_bkey++;
}
}
void verify_main_directory(uint32_t offset)
{
if(offset + 2 > fontdata_size) {
std::cerr << "Font verify error: Main directory offset out of range: " << offset << "." << std::endl;
exit(1);
}
uint32_t mseed = fontdata[offset++];
uint32_t msize = fontdata[offset++];
if(offset + msize > fontdata_size) {
std::cerr << "Font verify error: Main directory offset out of range: " << offset - 2 << "."
<< std::endl;
exit(1);
}
for(uint32_t i = 0; i < msize; i++)
verify_subdirectory(fontdata[offset++], mseed, msize, i);
}
int main()
{
if(fontdata_size == 0) {
std::cerr << "Font verify error: Empty fontdata." << std::endl;
exit(1);
}
verify_main_directory(fontdata[0]);
std::cerr << "Font verify successful!" << std::endl;
std::cerr << "Main directory entries: " << (mdir_use + mdir_nuse) << " (" << mdir_use << " used + "
<< mdir_nuse << " not_used)." << std::endl;
std::cerr << "Subdirectory entries: " << (sdir_gkey + sdir_bkey) << " (" << sdir_gkey << " good + "
<< sdir_bkey << " bad)." << std::endl;
std::cerr << "Distinct glyphs: " << (ftype0 + ftype1) << " (" << ftype0 << " narrow + "
<< ftype1 << " wide)." << std::endl;
return 0;
}