Get rid of need for host C++ compiler
This commit is contained in:
parent
3f5686bd32
commit
9f51c1d969
11 changed files with 177 additions and 518 deletions
16
Makefile
16
Makefile
|
@ -6,7 +6,6 @@ FONT_SRC := unifontfull-5.1.20080820.hex
|
|||
|
||||
#Compilers.
|
||||
CC := g++
|
||||
HOSTCC = $(CC)
|
||||
REALCC = $(CROSS_PREFIX)$(CC)
|
||||
|
||||
#Flags.
|
||||
|
@ -160,18 +159,11 @@ lsnes.$(EXECUTABLE_SUFFIX): $(CORE_OBJECTS) $(PLATFORM_OBJECTS)
|
|||
$(REALCC) -o $@ $^ $(CORE_LDFLAGS)
|
||||
|
||||
#Fonts.
|
||||
src/fonts/parsehexfont.$(OBJECT_SUFFIX): src/fonts/parsehexfont.cpp
|
||||
$(HOSTCC) $(HOST_CFLAGS) -c -o $@ $^
|
||||
src/fonts/parsehexfont.$(EXECUTABLE_SUFFIX): src/fonts/parsehexfont.$(OBJECT_SUFFIX)
|
||||
$(HOSTCC) $(HOST_LDFLAGS) -o $@ $^
|
||||
src/fonts/font.$(OBJECT_SUFFIX): src/fonts/$(FONT_SRC) src/fonts/parsehexfont.$(EXECUTABLE_SUFFIX)
|
||||
src/fonts/parsehexfont.$(EXECUTABLE_SUFFIX) <src/fonts/$(FONT_SRC) >src/fonts/font.cpp
|
||||
src/fonts/font.$(OBJECT_SUFFIX): src/fonts/$(FONT_SRC)
|
||||
echo "extern const char* font_hex_data = " >src/fonts/font.cpp
|
||||
sed -r -f src/fonts/fonttransform.sed <$^ >>src/fonts/font.cpp
|
||||
echo ";" >>src/fonts/font.cpp
|
||||
$(REALCC) $(CORE_CFLAGS) -c -o $@ src/fonts/font.cpp
|
||||
$(HOSTCC) $(HOST_CFLAGS) -o src/fonts/verifyhexfont.$(EXECUTABLE_SUFFIX) src/fonts/verifyhexfont.cpp src/fonts/font.cpp
|
||||
src/fonts/verifyhexfont.$(EXECUTABLE_SUFFIX)
|
||||
fonts/parsehexfont.$(EXECUTABLE_SUFFIX): fonts/parsehexfont.cpp
|
||||
$(HOSTCC) $(HOST_CFLAGS) -o $@ $^
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(PROGRAMS) src/*.$(OBJECT_SUFFIX) src/*/*.$(OBJECT_SUFFIX) avi/*.$(OBJECT_SUFFIX) src/fonts/font.o src/fonts/font.cpp
|
||||
|
|
|
@ -349,6 +349,11 @@ private:
|
|||
*/
|
||||
void clip_range(uint32_t origin, uint32_t size, int32_t base, int32_t& minc, int32_t& maxc) throw();
|
||||
|
||||
/**
|
||||
* Initialize font data.
|
||||
*/
|
||||
void do_init_font();
|
||||
|
||||
/**
|
||||
* Read font data for glyph.
|
||||
*
|
||||
|
|
14
manual.lyx
14
manual.lyx
|
@ -3729,20 +3729,6 @@ Note: If crosscompiling, this has to be crosscompiler, and CROSS_PREFIX
|
|||
is prepended.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
HOSTCC=<compiler>
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Host C++ compiler to use.
|
||||
Defaults to the same as CC.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Note: If crosscompiling, that has to be host compiler (the files produced
|
||||
will be run in the build process!)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
BSNES_IS_COMPAT=1
|
||||
\end_layout
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "lsnes.hpp"
|
||||
#include <snes/snes.hpp>
|
||||
|
||||
#include "core/misc.hpp"
|
||||
#include "core/png.hpp"
|
||||
#include "core/render.hpp"
|
||||
|
||||
|
@ -9,75 +10,180 @@
|
|||
#include <iomanip>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
extern uint32_t fontdata[];
|
||||
#define TAG_ZEROWIDTH 0
|
||||
#define TAG_NARROW 1
|
||||
#define TAG_WIDE 2
|
||||
#define TAG_TABULATION 3
|
||||
#define TAG_WIDTH_MASK 3
|
||||
#define TAG_LINECHANGE 4
|
||||
|
||||
extern const char* font_hex_data;
|
||||
|
||||
namespace
|
||||
{
|
||||
//This is Jenkin's MIX function.
|
||||
uint32_t keyhash(uint32_t key, uint32_t item, uint32_t mod) throw()
|
||||
std::vector<uint32_t> font_glyph_data;
|
||||
std::map<uint32_t, uint32_t> font_glyph_offsets;
|
||||
|
||||
uint32_t parse_word(const char* x)
|
||||
{
|
||||
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;
|
||||
char buf[9] = {0};
|
||||
char* end;
|
||||
memcpy(buf, x, 8);
|
||||
unsigned long v = strtoul(buf, &end, 16);
|
||||
if(end != buf + 8)
|
||||
v = 0xFFFFFFFFUL;
|
||||
//std::cerr << "Parse word " << buf << std::endl;
|
||||
return v;
|
||||
}
|
||||
|
||||
void init_font()
|
||||
{
|
||||
static bool iflag = false;
|
||||
if(iflag)
|
||||
return;
|
||||
//Special glyph data.
|
||||
font_glyph_data.resize(7);
|
||||
//Space & Unknown.
|
||||
font_glyph_data[0] = TAG_NARROW;
|
||||
font_glyph_data[1] = 0;
|
||||
font_glyph_data[2] = 0;
|
||||
font_glyph_data[3] = 0;
|
||||
font_glyph_data[4] = 0;
|
||||
//Tabulation.
|
||||
font_glyph_data[5] = TAG_TABULATION;
|
||||
//Linefeed.
|
||||
font_glyph_data[6] = TAG_ZEROWIDTH | TAG_LINECHANGE;
|
||||
|
||||
size_t lsptr = 0;
|
||||
uint32_t lc = 1;
|
||||
for(size_t i = 0;; i++) {
|
||||
//Skip spaces.
|
||||
switch(font_hex_data[i]) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
//Skip spaces at start of line.
|
||||
if(lsptr == i)
|
||||
lsptr++;
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\0': {
|
||||
char* end;
|
||||
uint32_t cp;
|
||||
size_t fdatastart;
|
||||
//Is this a comment?
|
||||
if(lsptr == i || font_hex_data[lsptr] == '#')
|
||||
goto skip_line;
|
||||
cp = strtoul(font_hex_data + lsptr, &end, 16);
|
||||
if(*end != ':') {
|
||||
messages << "Malformed line " << lc << " in font data" << std::endl;
|
||||
goto skip_line;
|
||||
}
|
||||
fdatastart = end - font_hex_data + 1;
|
||||
if(i - fdatastart == 32) {
|
||||
//Narrow glyph.
|
||||
font_glyph_offsets[cp] = font_glyph_data.size();
|
||||
font_glyph_data.push_back(TAG_NARROW);
|
||||
for(uint32_t k = 0; k < 4; k++)
|
||||
font_glyph_data.push_back(parse_word(end + 1 + 8 * k));
|
||||
} else if(i - fdatastart == 64) {
|
||||
//Wide glyph.
|
||||
font_glyph_offsets[cp] = font_glyph_data.size();
|
||||
font_glyph_data.push_back(TAG_WIDE);
|
||||
for(uint32_t k = 0; k < 8; k++)
|
||||
font_glyph_data.push_back(parse_word(end + 1 + 8 * k));
|
||||
} else {
|
||||
messages << "Malformed line " << lc << " in font data" << std::endl;
|
||||
goto skip_line;
|
||||
}
|
||||
skip_line:
|
||||
if(font_hex_data[i] != '\r' || font_hex_data[i + 1] != '\n')
|
||||
lc++;
|
||||
lsptr = i + 1;
|
||||
}
|
||||
};
|
||||
if(!font_hex_data[i])
|
||||
break;
|
||||
}
|
||||
|
||||
//Special characters.
|
||||
font_glyph_offsets[9] = 5;
|
||||
font_glyph_offsets[10] = 6;
|
||||
font_glyph_offsets[32] = 0;
|
||||
|
||||
uint32_t glyphs = 0;
|
||||
uint32_t glyphs_narrow = 0;
|
||||
uint32_t glyphs_wide = 0;
|
||||
uint32_t glyphs_special = 0;
|
||||
for(auto i : font_glyph_offsets) {
|
||||
if(font_glyph_data[i.second] == TAG_NARROW)
|
||||
glyphs_narrow++;
|
||||
else if(font_glyph_data[i.second] == TAG_WIDE)
|
||||
glyphs_wide++;
|
||||
else
|
||||
glyphs_special++;
|
||||
glyphs++;
|
||||
}
|
||||
messages << "Loaded font data: " << glyphs << " glyphs (" << glyphs_narrow << " narrow, " <<
|
||||
glyphs_wide << " wide, " << glyphs_special << " special)." << std::endl;
|
||||
iflag = true;
|
||||
}
|
||||
|
||||
inline uint32_t find_font_glyph_offset(uint32_t cp)
|
||||
{
|
||||
return font_glyph_offsets.count(cp) ? font_glyph_offsets[cp] : 0;
|
||||
}
|
||||
|
||||
inline uint32_t process_tag(uint32_t tag, int32_t& x, int32_t& y, int32_t orig_x)
|
||||
{
|
||||
uint32_t dwidth;
|
||||
switch(tag & TAG_WIDTH_MASK) {
|
||||
case TAG_ZEROWIDTH:
|
||||
dwidth = 0;
|
||||
break;
|
||||
case TAG_NARROW:
|
||||
dwidth = 8;
|
||||
break;
|
||||
case TAG_WIDE:
|
||||
dwidth = 16;
|
||||
break;
|
||||
case TAG_TABULATION:
|
||||
dwidth = 0x40 - (x & 0x3F);
|
||||
break;
|
||||
}
|
||||
x += dwidth;
|
||||
if(tag & TAG_LINECHANGE) {
|
||||
y += 16;
|
||||
x = orig_x;
|
||||
}
|
||||
return dwidth;
|
||||
}
|
||||
|
||||
inline bool is_visible(uint32_t tag)
|
||||
{
|
||||
return ((tag & TAG_WIDTH_MASK) == TAG_NARROW || (tag & TAG_WIDTH_MASK) == TAG_WIDE);
|
||||
}
|
||||
}
|
||||
|
||||
//Locate glyph in font. Returns <width, pointer> pair. NULL pointer should be interpretted as an empty
|
||||
//glyph.
|
||||
|
||||
void do_init_font()
|
||||
{
|
||||
init_font();
|
||||
}
|
||||
|
||||
std::pair<uint32_t, const uint32_t*> find_glyph(uint32_t codepoint, int32_t x, int32_t y, int32_t orig_x,
|
||||
int32_t& next_x, int32_t& next_y) throw()
|
||||
{
|
||||
uint32_t cwidth = 0;
|
||||
if(codepoint == 9) {
|
||||
cwidth = 64 - (x - orig_x) % 64;
|
||||
next_x = x + cwidth;
|
||||
next_y = y;
|
||||
return std::pair<uint32_t, const uint32_t*>(cwidth, NULL);
|
||||
} else if(codepoint == 10) {
|
||||
next_x = orig_x;
|
||||
next_y = y + 16;
|
||||
return std::pair<uint32_t, const uint32_t*>(0, NULL);
|
||||
} else if(codepoint == 32) {
|
||||
next_x = x + 8;
|
||||
next_y = y;
|
||||
return std::pair<uint32_t, const uint32_t*>(8, NULL);
|
||||
} else {
|
||||
uint32_t mdir = fontdata[0];
|
||||
uint32_t mseed = fontdata[mdir];
|
||||
uint32_t msize = fontdata[mdir + 1];
|
||||
uint32_t midx = keyhash(mseed, codepoint, msize);
|
||||
uint32_t sdir = fontdata[mdir + 2 + midx];
|
||||
if(!fontdata[sdir + 1]) {
|
||||
//Character not found.
|
||||
next_x = x + 8;
|
||||
next_y = y;
|
||||
return std::pair<uint32_t, const uint32_t*>(8, NULL);
|
||||
}
|
||||
uint32_t sseed = fontdata[sdir];
|
||||
uint32_t ssize = fontdata[sdir + 1];
|
||||
uint32_t sidx = keyhash(sseed, codepoint, ssize);
|
||||
if(fontdata[sdir + 2 + 2 * sidx] != codepoint) {
|
||||
//Character not found.
|
||||
next_x = x + 8;
|
||||
next_y = y;
|
||||
return std::pair<uint32_t, const uint32_t*>(8, NULL);
|
||||
}
|
||||
bool wide = (fontdata[fontdata[sdir + 2 + 2 * sidx + 1]] != 0);
|
||||
next_x = x + (wide ? 16 : 8);
|
||||
next_y = y;
|
||||
return std::make_pair(wide ? 16 : 8, fontdata + fontdata[sdir + 2 + 2 * sidx + 1] + 1);
|
||||
}
|
||||
init_font();
|
||||
next_x = x;
|
||||
next_y = y;
|
||||
uint32_t offset = find_font_glyph_offset(codepoint);
|
||||
uint32_t tag = font_glyph_data[offset];
|
||||
uint32_t dwidth = process_tag(tag, next_x, next_y, orig_x);
|
||||
bool visible = is_visible(tag);
|
||||
return std::pair<uint32_t, const uint32_t*>(dwidth, visible ? &font_glyph_data[offset + 1] : NULL);
|
||||
}
|
||||
|
||||
render_object::~render_object() throw()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "core/command.hpp"
|
||||
#include "core/misc.hpp"
|
||||
#include "core/render.hpp"
|
||||
#include "core/window.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
@ -186,6 +187,7 @@ void window::init()
|
|||
system_log << "-----------------------------------------------------------------------" << std::endl;
|
||||
system_log << "lsnes started at " << buffer << std::endl;
|
||||
system_log << "-----------------------------------------------------------------------" << std::endl;
|
||||
do_init_font();
|
||||
graphics_init();
|
||||
sound_init();
|
||||
joystick_init();
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆<EFBFBD><EFBFBD><EFBFBD>辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2
src/fonts/fonttransform.sed
Normal file
2
src/fonts/fonttransform.sed
Normal file
|
@ -0,0 +1,2 @@
|
|||
s/^(.*)$/"\1\\n"/g
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
s = "";
|
||||
for i = 128,255 do
|
||||
s = s .. string.char(i);
|
||||
end
|
||||
io.stdout:write(s);
|
|
@ -1,258 +0,0 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
|
||||
std::map<uint32_t, uint32_t> glyph_index;
|
||||
std::map<std::string, uint32_t> glyph_offsets;
|
||||
std::map<uint32_t, std::string> glyphs;
|
||||
uint32_t next_offset = 1;
|
||||
|
||||
void add_glyph(uint32_t codepoint, const std::string& appearence)
|
||||
{
|
||||
if(((codepoint >> 16) > 10) || ((codepoint & 0x1FF800) == 0xD800)) {
|
||||
std::cerr << "Illegal codepoint " << std::hex << codepoint << "." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if(!glyph_offsets.count(appearence)) {
|
||||
if(appearence.find_first_not_of("0123456789ABCDEFabcdef") < appearence.length()) {
|
||||
std::cerr << "Invalid font representation (invalid hex char)." << std::endl;
|
||||
std::cerr << "Faulty representation: '" << appearence << "'." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
glyph_offsets[appearence] = next_offset;
|
||||
glyph_index[next_offset] = codepoint;
|
||||
if(appearence.length() == 32)
|
||||
next_offset += 5;
|
||||
else if(appearence.length() == 64)
|
||||
next_offset += 9;
|
||||
else {
|
||||
std::cerr << "Invalid font representation (length " << appearence.length() << ")."
|
||||
<< std::endl;
|
||||
std::cerr << "Faulty representation: '" << appearence << "'." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
glyphs[codepoint] = appearence;
|
||||
}
|
||||
|
||||
uint32_t bucket_size(uint32_t items)
|
||||
{
|
||||
if(items <= 4)
|
||||
return items;
|
||||
return static_cast<uint32_t>(pow(items, 1.5));
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
uint32_t wrong_key(uint32_t key, uint32_t hash, uint32_t mod)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
if(mod <= 1)
|
||||
return 0;
|
||||
while(keyhash(key, i, mod) == hash)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
std::pair<uint32_t, uint32_t> make_subdirectory(std::vector<uint32_t>& items)
|
||||
{
|
||||
if(items.size() < 2)
|
||||
return std::make_pair(0, items.size());
|
||||
std::vector<uint32_t> memory;
|
||||
memory.resize(bucket_size(items.size()));
|
||||
uint32_t seed = 1;
|
||||
unsigned tries = 0;
|
||||
while(true) {
|
||||
//Safety hatch: If unsuccessful too many times, increase the hash size.
|
||||
if(tries == 100) {
|
||||
memory.resize(memory.size() + 1);
|
||||
tries = 0;
|
||||
}
|
||||
bool success = true;
|
||||
seed = rand();
|
||||
for(uint32_t i = 0; i < memory.size(); i++)
|
||||
memory[i] = 0xFFFFFFFFUL;
|
||||
for(uint32_t i = 0; i < items.size(); i++) {
|
||||
uint32_t j = keyhash(seed, items[i], memory.size());
|
||||
if(memory[j] != 0xFFFFFFFFUL) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
memory[j] = items[i];
|
||||
}
|
||||
if(success)
|
||||
break;
|
||||
tries++;
|
||||
}
|
||||
return std::make_pair(seed, memory.size());
|
||||
}
|
||||
|
||||
void write_subdirectory(std::vector<uint32_t>& items, std::pair<uint32_t, uint32_t> p,
|
||||
uint32_t badkey)
|
||||
{
|
||||
if(!p.second)
|
||||
return;
|
||||
std::vector<uint32_t> memory;
|
||||
std::cout << "," << p.first << "UL," << p.second << "UL";
|
||||
memory.resize(p.second);
|
||||
for(uint32_t i = 0; i < memory.size(); i++)
|
||||
memory[i] = badkey;
|
||||
for(uint32_t i = 0; i < items.size(); i++)
|
||||
memory[keyhash(p.first, items[i], memory.size())] = items[i];
|
||||
for(uint32_t i = 0; i < memory.size(); i++) {
|
||||
if(memory[i] != badkey)
|
||||
std::cout << "," << memory[i] << "UL," << glyph_offsets[glyphs[memory[i]]] << "UL";
|
||||
else
|
||||
std::cout << "," << badkey << "UL,0UL";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
uint32_t glyph_part_string(const std::string& str)
|
||||
{
|
||||
return strtoul(str.c_str(), NULL, 16);
|
||||
}
|
||||
|
||||
void write_glyphs()
|
||||
{
|
||||
for(std::map<uint32_t, uint32_t>::iterator i = glyph_index.begin(); i != glyph_index.end(); ++i) {
|
||||
std::string glyph = glyphs[i->second];
|
||||
if(glyph.length() == 32) {
|
||||
std::cout << ",0";
|
||||
for(unsigned i = 0; i < 32; i += 8)
|
||||
std::cout << "," << glyph_part_string(glyph.substr(i, 8)) << "UL";
|
||||
} else if(glyph.length() == 64) {
|
||||
std::cout << ",1";
|
||||
for(unsigned i = 0; i < 64; i += 8)
|
||||
std::cout << "," << glyph_part_string(glyph.substr(i, 8)) << "UL";
|
||||
} else {
|
||||
std::cerr << "INTERNAL ERROR: Invalid glyph data" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void write_main_directory(uint32_t seed, std::vector<std::vector<uint32_t> >& main_directory,
|
||||
std::vector<std::pair<uint32_t, uint32_t> >& subdirectories)
|
||||
{
|
||||
std::cout << "," << seed << "UL";
|
||||
std::cout << "," << main_directory.size() << "UL";
|
||||
uint32_t subdir_offset = next_offset + 4 + main_directory.size();
|
||||
for(size_t i = 0; i < main_directory.size(); i++) {
|
||||
if(subdirectories[i].second) {
|
||||
std::cout << "," << subdir_offset << "UL";
|
||||
subdir_offset = subdir_offset + 2 + 2 * subdirectories[i].second;
|
||||
} else
|
||||
std::cout << "," << next_offset << "UL";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string line;
|
||||
srand(time(NULL));
|
||||
while(std::getline(std::cin, line)) {
|
||||
if(line[line.length() - 1] == '\r')
|
||||
line = line.substr(0, line.length() - 1);
|
||||
size_t split = line.find_first_of("#:");
|
||||
if(split > line.length() || line[split] == '#')
|
||||
continue;
|
||||
std::string codepoint = line.substr(0, split);
|
||||
std::string appearence = line.substr(split + 1);
|
||||
uint32_t cp = 0;
|
||||
char* end;
|
||||
cp = strtoul(codepoint.c_str(), &end, 16);
|
||||
if(*end) {
|
||||
std::cerr << "Invalid codepoint number '" << codepoint << "." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
add_glyph(cp, appearence);
|
||||
}
|
||||
std::cerr << "Loaded " << glyphs.size() << " glyphs (" << glyph_offsets.size() << " distinct)." << std::endl;
|
||||
if(!glyphs.size()) {
|
||||
std::cerr << "Need at least 1 glyph." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
uint32_t best_seed = 0;
|
||||
uint32_t best_score = 0xFFFFFFFFUL;
|
||||
uint32_t main_directory_size = glyphs.size();
|
||||
for(unsigned i = 0; i < 1000; i++) {
|
||||
if(i % 10 == 0)
|
||||
std::cerr << "." << std::flush;
|
||||
uint32_t seed = rand();
|
||||
std::vector<uint32_t> bucket_items;
|
||||
bucket_items.resize(main_directory_size);
|
||||
for(uint32_t i = 0; i < main_directory_size; i++)
|
||||
bucket_items[i] = 0;
|
||||
for(std::map<uint32_t, std::string>::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
||||
bucket_items[keyhash(seed, i->first, main_directory_size)]++;
|
||||
uint32_t score = 0;
|
||||
for(uint32_t i = 0; i < main_directory_size; i++)
|
||||
if(bucket_items[i])
|
||||
score = score + 2 * bucket_size(bucket_items[i]) + 3;
|
||||
else
|
||||
score = score + 1;
|
||||
if(score < best_score) {
|
||||
best_seed = seed;
|
||||
best_score = score;
|
||||
}
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Best estimated score: " << best_score << " for seed " << best_seed << "." << std::endl;
|
||||
std::vector<std::vector<uint32_t> > main_directory;
|
||||
std::vector<std::pair<uint32_t, uint32_t> > subdirectories;
|
||||
main_directory.resize(main_directory_size);
|
||||
subdirectories.resize(main_directory_size);
|
||||
for(std::map<uint32_t, std::string>::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
||||
main_directory[keyhash(best_seed, i->first, main_directory_size)].push_back(i->first);
|
||||
uint32_t update_interval = main_directory_size / 10;
|
||||
unsigned real_score = 0;
|
||||
for(size_t i = 0; i < main_directory.size(); i++) {
|
||||
if((i % update_interval) == 0)
|
||||
std::cerr << "." << std::flush;
|
||||
subdirectories[i] = make_subdirectory(main_directory[i]);
|
||||
if(subdirectories[i].second)
|
||||
real_score = real_score + 2 * subdirectories[i].second + 3;
|
||||
else
|
||||
real_score = real_score + 1;
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Final score: " << real_score << " (" << next_offset + real_score + 4 << " elements)."
|
||||
<< std::endl;
|
||||
std::cout << "#include <cstdint>" << std::endl;
|
||||
std::cout << "uint32_t fontdata_size = " << next_offset + real_score + 4 << ";" << std::endl;
|
||||
std::cout << "uint32_t fontdata[] = {";
|
||||
std::cout << next_offset + 2 << "UL";
|
||||
write_glyphs();
|
||||
std::cout << ",0,0" << std::endl;
|
||||
write_main_directory(best_seed, main_directory, subdirectories);
|
||||
for(size_t i = 0; i < main_directory.size(); i++)
|
||||
write_subdirectory(main_directory[i], subdirectories[i], wrong_key(best_seed, i, main_directory_size));
|
||||
std::cout << "};" << std::endl;
|
||||
return 0;
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
#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;
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
uint8_t data[4096];
|
||||
|
||||
uint16_t hidxtab[128] = {
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
};
|
||||
|
||||
uint16_t idx(uint8_t ch)
|
||||
{
|
||||
if(ch < 128)
|
||||
return ch;
|
||||
else
|
||||
return hidxtab[ch - 128];
|
||||
}
|
||||
|
||||
void write_glyph(uint16_t cp, uint8_t* d)
|
||||
{
|
||||
std::cout << std::hex << std::setw(4) << std::setfill('0') << cp << ":";
|
||||
for(unsigned i = 0; i < 16; i++)
|
||||
std::cout << std::hex << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<int>(static_cast<unsigned char>(d[i]));
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void write_glyphs()
|
||||
{
|
||||
for(unsigned i = 0; i < 256; i++)
|
||||
write_glyph(idx(i), data + 16 * i);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cin.read(reinterpret_cast<char*>(data), 4096);
|
||||
write_glyphs();
|
||||
}
|
Loading…
Add table
Reference in a new issue