1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-10-17 22:20:41 +00:00

font system redesigned, font selection

This commit is contained in:
Zeno Rogue 2024-07-10 00:03:00 +02:00
parent 92d7eafcc3
commit 6bbd57ecbe
5 changed files with 128 additions and 67 deletions

View File

@ -155,9 +155,6 @@ EX int getnext(const char* s, int& i) {
} }
#if CAP_SDLTTF #if CAP_SDLTTF
const int max_font_size = 288;
TTF_Font* font[max_font_size+1];
void fix_font_size(int& size) { void fix_font_size(int& size) {
if(size < 1) size = 1; if(size < 1) size = 1;
if(size > max_font_size) size = max_font_size; if(size > max_font_size) size = max_font_size;
@ -227,25 +224,36 @@ EX void present_screen() {
#if CAP_SDLTTF #if CAP_SDLTTF
#define DEFAULT_FONT "DejaVuSans-Bold.ttf" EX vector<string> font_filenames = {
"DejaVuSans-Bold.ttf",
"DejaVuSans.ttf",
"cmunss.ttf",
"NotoSans-Regular.ttf",
"OpenDyslexic3-Regular.ttf",
"font.ttf",
"font.otf"
};
EX vector<pair<string, string>> font_names = {
{"DejaVu Sans Bold", ""},
{"DejaVu Sans", ""},
{"Computer Modern Sans", ""},
{"Noto Sans", ""},
{"OpenDyslexic3-Regular", ""},
{"TTF font", ""},
{"OTF font", ""}
};
EX int last_font_id = 0;
EX int font_id = 0;
#ifdef FONTCONFIG #ifdef FONTCONFIG
/** if this is non-empty, find the font using fontconfig */ TTF_Font* findfont(int siz) {
EX string font_to_find = DEFAULT_FONT;
#endif
/** actual font path */
EX string fontpath = ISWEB ? "sans-serif" : string(HYPERFONTPATH) + DEFAULT_FONT;
const string& findfont() {
#ifdef FONTCONFIG
if(font_to_find == "") return fontpath;
FcPattern *pat; FcPattern *pat;
FcResult result; FcResult result;
if (!FcInit()) { if (!FcInit()) return nullptr;
return fontpath; pat = FcNameParse((FcChar8 *)cfont->filename.c_str());
}
pat = FcNameParse((FcChar8 *)font_to_find.c_str());
FcConfigSubstitute(0, pat, FcMatchPattern); FcConfigSubstitute(0, pat, FcMatchPattern);
FcDefaultSubstitute(pat); FcDefaultSubstitute(pat);
@ -254,31 +262,33 @@ const string& findfont() {
if (match) { if (match) {
FcChar8 *file; FcChar8 *file;
if (FcPatternGetString(match, FC_FILE, 0, &file) == FcResultMatch) { if (FcPatternGetString(match, FC_FILE, 0, &file) == FcResultMatch) {
fontpath = (const char *)file; cfont->filename = (const char *)file;
} }
FcPatternDestroy(match); FcPatternDestroy(match);
} }
FcPatternDestroy(pat); FcPatternDestroy(pat);
FcFini(); FcFini();
font_to_find = ""; cfont->use_fontconfig = false;
if(debugflags & DF_INIT) println(hlog, "fontpath is: ", fontpath); if(debugflags & DF_INIT) println(hlog, "fontpath is: ", cfont->filename);
#endif return TTF_OpenFont(cfont->filename, siz);
return fontpath;
} }
#endif
void loadfont(int siz) { void loadfont(int siz) {
fix_font_size(siz); fix_font_size(siz);
if(!font[siz]) { auto& cf = cfont->font[siz];
font[siz] = TTF_OpenFont(findfont().c_str(), siz); if(!cf) {
// Destination set by ./configure (in the GitHub repository) if(cf == NULL) cf = TTF_OpenFont(find_file(cfont->filename).c_str(), siz);
#ifdef FONTDESTDIR
if (font[siz] == NULL) { #ifdef FONTCONFIG
font[siz] = TTF_OpenFont(FONTDESTDIR, siz); if(cf == NULL && cfont->use_fontconfig)
} cf = find_font_using_fontconfig(siz);
#endif #endif
if (font[siz] == NULL) {
printf("error: Font file not found: %s\n", fontpath.c_str()); if(cf == NULL) {
exit(1); printf("error: Font file not found: %s\n", cfont->filename.c_str());
if(font_id == 0) throw hr_exception("font file not found");
font_id = 0; set_cfont(); loadfont(siz);
} }
} }
} }
@ -293,7 +303,7 @@ int textwidth(int siz, const string &str) {
loadfont(siz); loadfont(siz);
int w, h; int w, h;
TTF_SizeUTF8(font[siz], str.c_str(), &w, &h); TTF_SizeUTF8(cfont->font[siz], str.c_str(), &w, &h);
// printf("width = %d [%d]\n", w, isize(str)); // printf("width = %d [%d]\n", w, isize(str));
return w; return w;
@ -435,6 +445,40 @@ EX int next_p2 (int a ) {
return rval; return rval;
} }
#if HDR
constexpr int max_glfont_size = 72;
constexpr int max_font_size = 288;
struct fontdata {
string filename;
#if FONTCONFIG
bool use_fontconfig;
#endif
struct glfont_t* glfont[max_glfont_size+1];
#if CAP_SDLTTF
TTF_Font* font[max_font_size+1];
#endif
~fontdata();
};
#endif
EX map<string, fontdata> fontdatas;
EX fontdata *cfont;
EX fontdata* font_by_name(string fname) {
auto& fd = fontdatas[fname];
if(fd.filename == "") {
fd.filename = fname;
#if FONTCONFIG
fd.use_fontconfig = true;
#endif
for(int i=0; i<=max_glfont_size; i++) fd.glfont[i] = nullptr;
for(int i=0; i<=max_font_size; i++) fd.font[i] = nullptr;
}
return &fd;
}
#if CAP_GLFONT #if CAP_GLFONT
#define CHARS (128+NUMEXTRA) #define CHARS (128+NUMEXTRA)
@ -450,18 +494,14 @@ struct glfont_t {
//GLuint list_base; // Holds The First Display List ID //GLuint list_base; // Holds The First Display List ID
vector<charinfo_t> chars; vector<charinfo_t> chars;
}; };
const int max_glfont_size = 72;
#endif #endif
EX glfont_t *glfont[max_glfont_size+1];
typedef Uint16 texturepixel; typedef Uint16 texturepixel;
#define FONTTEXTURESIZE 2048 #define FONTTEXTURESIZE 4096
int curx = 0, cury = 0, theight = 0; int curx = 0, cury = 0, theight = 0;
texturepixel fontdata[FONTTEXTURESIZE][FONTTEXTURESIZE]; texturepixel fontpixels[FONTTEXTURESIZE][FONTTEXTURESIZE];
void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) { void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) {
#if CAP_TABFONT #if CAP_TABFONT
@ -480,7 +520,7 @@ void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) {
theight = max(theight, otheight); theight = max(theight, otheight);
for(int j=0; j<otheight;j++) for(int i=0; i<otwidth; i++) { for(int j=0; j<otheight;j++) for(int i=0; i<otwidth; i++) {
fontdata[j+cury][i+curx] = fontpixels[j+cury][i+curx] =
#if CAP_TABFONT #if CAP_TABFONT
(i>=otwidth || j>=otheight) ? 0 : (tpix[tpixindex++] * 0x100) | 0xFF; (i>=otwidth || j>=otheight) ? 0 : (tpix[tpixindex++] * 0x100) | 0xFF;
#else #else
@ -501,17 +541,17 @@ void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) {
} }
EX void init_glfont(int size) { EX void init_glfont(int size) {
if(glfont[size]) return; if(cfont->glfont[size]) return;
DEBBI(DF_GRAPH, ("init GL font: ", size)); DEBBI(DF_GRAPH, ("init GL font: ", size));
#if !CAP_TABFONT #if !CAP_TABFONT
loadfont(size); loadfont(size);
if(!font[size]) return; if(!cfont->font[size]) return;
#endif #endif
glfont[size] = new glfont_t; cfont->glfont[size] = new glfont_t;
glfont_t& f(*(glfont[size])); glfont_t& f(*(cfont->glfont[size]));
f.chars.resize(CHARS); f.chars.resize(CHARS);
@ -527,7 +567,7 @@ EX void init_glfont(int size) {
for(int y=0; y<FONTTEXTURESIZE; y++) for(int y=0; y<FONTTEXTURESIZE; y++)
for(int x=0; x<FONTTEXTURESIZE; x++) for(int x=0; x<FONTTEXTURESIZE; x++)
fontdata[y][x] = 0; fontpixels[y][x] = 0;
#if CAP_TABFONT #if CAP_TABFONT
resetTabFont(); resetTabFont();
@ -550,10 +590,10 @@ EX void init_glfont(int size) {
fix_font_size(siz); fix_font_size(siz);
if(ch < 128) { if(ch < 128) {
str[0] = ch; str[0] = ch;
txt = TTF_RenderText_Blended(font[siz], str, white); txt = TTF_RenderText_Blended(cfont->font[siz], str, white);
} }
else { else {
txt = TTF_RenderUTF8_Blended(font[siz], natchars[ch-128], white); txt = TTF_RenderUTF8_Blended(cfont->font[siz], natchars[ch-128], white);
} }
if(txt == NULL) continue; if(txt == NULL) continue;
#if CAP_CREATEFONT #if CAP_CREATEFONT
@ -572,7 +612,7 @@ EX void init_glfont(int size) {
glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, FONTTEXTURESIZE, theight, 0, glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, FONTTEXTURESIZE, theight, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
fontdata); fontpixels);
for(int ch=0; ch<CHARS; ch++) f.chars[ch].ty0 /= theight, f.chars[ch].ty1 /= theight; for(int ch=0; ch<CHARS; ch++) f.chars[ch].ty0 /= theight, f.chars[ch].ty1 /= theight;
@ -595,9 +635,9 @@ int gl_width(int size, const char *s) {
#endif #endif
init_glfont(gsiz); init_glfont(gsiz);
if(!glfont[gsiz]) return 0; if(!cfont->glfont[gsiz]) return 0;
glfont_t& f(*glfont[gsiz]); glfont_t& f(*cfont->glfont[gsiz]);
int x = 0; int x = 0;
for(int i=0; s[i];) { for(int i=0; s[i];) {
@ -628,9 +668,9 @@ bool gl_print(int x, int y, int shift, int size, const char *s, color_t color, i
#endif #endif
init_glfont(gsiz); init_glfont(gsiz);
if(!glfont[gsiz]) return false; if(!cfont->glfont[gsiz]) return false;
glfont_t& f(*glfont[gsiz]); glfont_t& f(*cfont->glfont[gsiz]);
int tsize = 0; int tsize = 0;
@ -692,9 +732,10 @@ EX void resetGL() {
DEBBI(DF_INIT | DF_GRAPH, ("reset GL")) DEBBI(DF_INIT | DF_GRAPH, ("reset GL"))
callhooks(hooks_resetGL); callhooks(hooks_resetGL);
#if CAP_GLFONT #if CAP_GLFONT
for(int i=0; i<=max_glfont_size; i++) if(glfont[i]) { for(auto& cf: fontdatas)
delete glfont[i]; for(int i=0; i<=max_glfont_size; i++) if(cf.second.glfont[i]) {
glfont[i] = NULL; delete cf.second.glfont[i];
cf.second.glfont[i] = NULL;
} }
#endif #endif
#if MAXMDIM >= 4 #if MAXMDIM >= 4
@ -819,7 +860,7 @@ EX bool displaystr(int x, int y, int shift, int size, const char *str, color_t c
fix_font_size(size); fix_font_size(size);
loadfont(size); loadfont(size);
SDL_Surface *txt = ((vid.antialias & AA_FONT)?TTF_RenderUTF8_Blended:TTF_RenderUTF8_Solid)(font[size], str, col); SDL_Surface *txt = ((vid.antialias & AA_FONT)?TTF_RenderUTF8_Blended:TTF_RenderUTF8_Solid)(cfont->font[size], str, col);
if(txt == NULL) return false; if(txt == NULL) return false;
@ -1436,22 +1477,26 @@ EX int SDL_Init1(Uint32 flags) {
} }
#endif #endif
EX void set_cfont() {
cfont = font_by_name(font_filenames[last_font_id = font_id]);
}
EX void init_font() { EX void init_font() {
#if CAP_SDLTTF #if CAP_SDLTTF
if(TTF_Init() != 0) { if(TTF_Init() != 0) {
printf("Failed to initialize TTF.\n"); printf("Failed to initialize TTF.\n");
exit(2); exit(2);
} }
set_cfont();
#endif #endif
} }
EX void close_font() { fontdata::~fontdata() {
#if CAP_SDLTTF #if CAP_SDLTTF
for(int i=0; i<=max_font_size; i++) if(font[i]) { for(int i=0; i<=max_font_size; i++) if(font[i]) {
TTF_CloseFont(font[i]); TTF_CloseFont(font[i]);
font[i] = nullptr; font[i] = nullptr;
} }
TTF_Quit();
#endif #endif
#if CAL_GLFONT #if CAL_GLFONT
for(int i=0; i<=max_glfont_size; i++) if(glfont[i]) { for(int i=0; i<=max_glfont_size; i++) if(glfont[i]) {
@ -1461,6 +1506,11 @@ EX void close_font() {
#endif #endif
} }
EX void close_font() {
fontdatas.clear();
TTF_Quit();
}
EX void init_graph() { EX void init_graph() {
#if CAP_SDL #if CAP_SDL
if (SDL_Init1(SDL_INIT_VIDEO) == -1) if (SDL_Init1(SDL_INIT_VIDEO) == -1)

View File

@ -172,14 +172,7 @@ int arg::readCommon() {
else if(argis("-nogui")) { PHASE(1); noGUI = true; } else if(argis("-nogui")) { PHASE(1); noGUI = true; }
#ifndef EMSCRIPTEN #ifndef EMSCRIPTEN
#if CAP_SDL #if CAP_SDL
else if(argis("-font")) { PHASE(1); shift(); fontpath = args(); else if(argis("-font")) { PHASE(1); shift(); font_id = isize(font_filenames); font_filenames.push_back(args()); font_names.push_back({args(), "commandline"}); }
#ifdef FONTCONFIG
font_to_find = "";
#endif
}
#ifdef FONTCONFIG
else if(argis("-find-font")) { PHASE(1); shift(); font_to_find = args(); }
#endif
#endif #endif
#endif #endif

View File

@ -1013,6 +1013,16 @@ EX purehookset hooks_configfile;
EX ld mapfontscale = 100; EX ld mapfontscale = 100;
EX void font_reaction() {
if(among(font_id, 5, 6)) {
int fid = font_id;
font_id = last_font_id;
dialog::openFileDialog(font_filenames[fid], XLAT("font to use:"), fid == 5 ? ".ttf" : ".otf", [fid] () {
font_id = fid; return true;
});
}
}
EX void initConfig() { EX void initConfig() {
// basic config // basic config
@ -1099,6 +1109,11 @@ EX void initConfig() {
initcs(vid.cs); paramset(vid.cs, "single"); initcs(vid.cs); paramset(vid.cs, "single");
param_b(vid.samegender, "princess choice", false); param_b(vid.samegender, "princess choice", false);
param_i(vid.language, "language", -1); param_i(vid.language, "language", -1);
param_enum(font_id, "font_id", 0)
->editable(font_names, "select font", 'f')
->manual_reaction = font_reaction;
param_str(font_filenames[5], "ttf_font");
param_str(font_filenames[6], "otf_font");
param_b(vid.drawmousecircle, "mouse circle", ISMOBILE || ISPANDORA); param_b(vid.drawmousecircle, "mouse circle", ISMOBILE || ISPANDORA);
param_b(vid.revcontrol, "reverse control", false); param_b(vid.revcontrol, "reverse control", false);
#if CAP_AUDIO #if CAP_AUDIO
@ -2424,6 +2439,8 @@ EX void configureInterface() {
dialog::add_action_push(selectLanguageScreen); dialog::add_action_push(selectLanguageScreen);
#endif #endif
add_edit(font_id);
dialog::addSelItem(XLAT("player character"), numplayers() > 1 ? "" : csname(vid.cs), 'g'); dialog::addSelItem(XLAT("player character"), numplayers() > 1 ? "" : csname(vid.cs), 'g');
dialog::add_action_push(showCustomizeChar); dialog::add_action_push(showCustomizeChar);
if(getcstat == 'g') mouseovers = XLAT("Affects looks and grammar"); if(getcstat == 'g') mouseovers = XLAT("Affects looks and grammar");

View File

@ -2872,7 +2872,7 @@ EX hyperpoint default_pointfunction(ld x, ld y) {
#if !CAP_EXTFONT #if !CAP_EXTFONT
EX void write_in_space(const shiftmatrix& V, int fsize, double size, const string& s, color_t col, int frame IS(0), int align IS(8), PPR prio IS(PPR::TEXT), pointfunction pf IS(default_pointfunction)) { EX void write_in_space(const shiftmatrix& V, int fsize, double size, const string& s, color_t col, int frame IS(0), int align IS(8), PPR prio IS(PPR::TEXT), pointfunction pf IS(default_pointfunction)) {
init_glfont(fsize); init_glfont(fsize);
glfont_t& f(*(glfont[fsize])); glfont_t& f(*(cfont->glfont[fsize]));
finf.texture_id = f.texture; finf.texture_id = f.texture;
int fstart = isize(finf.tvertices); int fstart = isize(finf.tvertices);

View File

@ -5600,6 +5600,7 @@ EX void calcparam() {
ld fov = vid.fov * degree / 2; ld fov = vid.fov * degree / 2;
cd->tanfov = sin(fov) / (cos(fov) + get_stereo_param()); cd->tanfov = sin(fov) / (cos(fov) + get_stereo_param());
set_cfont();
callhooks(hooks_calcparam); callhooks(hooks_calcparam);
reset_projection(); reset_projection();
} }