diff --git a/CMakeLists.txt b/CMakeLists.txt index b5ab69905..9a2254040 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,15 @@ IF(FREETYPE_FOUND) INCLUDE_DIRECTORIES( ${FREETYPE_INCLUDE_DIRS} ) SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};LIBFREETYPE_STATIC) SET(FTE_LIBS ${FTE_LIBS} ${FREETYPE_LIBRARIES}) + + FIND_PACKAGE(Fontconfig) + IF(Fontconfig_FOUND) + INCLUDE_DIRECTORIES( ${Fontconfig_INCLUDE_DIRS} ) + SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};LIBFONTCONFIG_STATIC) + SET(FTE_LIBS ${FTE_LIBS} ${Fontconfig_LIBRARIES}) + ELSEIF() + MESSAGE(WARNING "fontconfig library NOT available. I hope you're not using any system fonts.") + ENDIF() ELSE() MESSAGE(WARNING "freetype library NOT available. I hope you're okay with ascii.") SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_FREETYPE) diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 6bd035f9e..7eb01d347 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -1075,7 +1075,22 @@ void QDECL R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) } #ifdef AVAIL_FREETYPE -#if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX) +#if defined(LIBFONTCONFIG_STATIC) +#include +static int QDECL SortCompareFonts(const void *av, const void *bv) +{ //qsort compare + const FcPattern *af = *(FcPattern *const*const)av, *bf = *(FcPattern *const*const)bv; + FcChar8 *as, *bs; + int r = 0; + if (FcPatternGetString(af, FC_FAMILY, 0, &as) == FcResultMatch && FcPatternGetString(bf, FC_FAMILY, 0, &bs) == FcResultMatch) + { + r = strcmp(as, bs); + if (!r && FcPatternGetString(af, FC_STYLE, 0, &as) == FcResultMatch && FcPatternGetString(bf, FC_STYLE, 0, &bs) == FcResultMatch) + r = strcmp(as, bs); + } + return r; +} +#elif defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX) #include qboolean R2D_Font_WasAdded(char *buffer, char *fontfilename) { @@ -1181,6 +1196,45 @@ void R2D_Font_Changed(void) { #ifndef AVAIL_FREETYPE Cvar_Set(&gl_font, ""); +#elif defined(LIBFONTCONFIG_STATIC) + Cvar_Set(&gl_font, ""); + { + FcConfig *config = FcInitLoadConfigAndFonts(); + FcPattern *pat = FcPatternCreate(); + FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, (char *) 0); + FcFontSet *fs = FcFontList(config, pat, os); + + if (fs) + { + int i; + FcChar8 *oldfam = NULL; + FcPattern **fonts = BZ_Malloc(sizeof(*fonts)*fs->nfont); + memcpy(fonts, fs->fonts, sizeof(*fonts)*fs->nfont); + qsort(fonts, fs->nfont, sizeof(*fonts), SortCompareFonts); + for (i=0; fs && i < fs->nfont; i++) + { + FcPattern *font = fonts[i]; + FcChar8 *style, *family; + if (FcPatternGetString(font, FC_FAMILY, 0, &family) == FcResultMatch && FcPatternGetString(font, FC_STYLE, 0, &style) == FcResultMatch) + { + if (!oldfam || strcmp(oldfam, family)) + { + if (oldfam) + Con_Printf("\n"); + oldfam = family; + Con_Printf("^["S_COLOR_WHITE"%s\\type\\/gl_font %s^]: ", family, family); + } + Con_Printf(" \t^[%s\\type\\/gl_font %s?style=%s^]", style, family, style); + } + } + if (oldfam) + Con_Printf("\n"); + BZ_Free(fonts); + FcFontSetDestroy(fs); + } + FcObjectSetDestroy(os); + FcPatternDestroy(pat); + } #elif defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) && !defined(_XBOX) BOOL (APIENTRY *pChooseFontW)(LPCHOOSEFONTW) = NULL; dllfunction_t funcs[] = diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 7453625ee..5bfe78096 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -13,6 +13,20 @@ #endif #include +/* Font Names: + primaryface[,altface[...]][?primaryarg[&arg[...]]][:[secondaryface[,altface[...]]][?secondaryargs]] + + args: + col=r,g,b -- tint the font (overriding the game's normal tint). only arg allowed when the secondary face is omitted. + fmt=q -- quake-style raster font with quake's own codepage (no fallbacks needed for the weird glyphs). + fmt=l -- quake-style raster font with io8859-1(latin-1) codepage + fmt=w -- quake-style raster font with windows1252 codepage (for more glyphs than latin-1) + fmt=k -- quake-style raster font with koi8-u codepage (apparently its somewhat common in the quake community) + fmt=h -- halflife-style all-on-one-line raster font + aspect=0.5 -- raster font is squished horizontally + style -- list of modifiets for inexact family font matching for system fonts +*/ + void Font_Init(void); void Font_Shutdown(void); struct font_s *Font_LoadFont(const char *fontfilename, float height, float scale, int outline, unsigned int flags); @@ -1762,6 +1776,9 @@ qboolean Font_LoadKexFont(struct font_s *f, int fheight, const char *fontfilenam } #ifdef AVAIL_FREETYPE +#if defined(LIBFONTCONFIG_STATIC) +#include +#endif extern cvar_t dpcompat_smallerfonts; int Font_ChangeFTSize(fontface_t *qface, int pixelheight) { @@ -1813,7 +1830,7 @@ int Font_ChangeFTSize(fontface_t *qface, int pixelheight) } return pixelheight; } -qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfilename) +qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfilename, const char *styles) { fontface_t *qface; FT_Face face = NULL; @@ -1913,7 +1930,34 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfil } } -#if defined(_WIN32) +#if defined(LIBFONTCONFIG_STATIC) + if (error && !strchr(fontfilename, '/')) + { + FcConfig *config = FcInitLoadConfigAndFonts(); + FcResult res; + FcPattern *font; + FcPattern *pat; + + //FcNameParse takes something of the form: "family:style1:style2". we already swapped spaces for : in styles. + if (styles) + pat = FcNameParse((const FcChar8*)va("%s:%s", fontfilename, styles)); + else + pat = FcNameParse((const FcChar8*)fontfilename); + FcConfigSubstitute(config, pat, FcMatchPattern); + FcDefaultSubstitute(pat); + + // find the font + font = FcFontMatch(config, pat, &res); + if (font) + { + FcChar8 *file = NULL; + if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) + error = pFT_New_Face(fontlib, file, 0, &face); //'file' should be a system path + FcPatternDestroy(font); + } + FcPatternDestroy(pat); + } +#elif defined(_WIN32) if (error) { static qboolean firsttime = true; @@ -2285,6 +2329,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal char *parms; int height = ((vheight * vid.rotpixelheight)/vid.height) + 0.5; char facename[MAX_QPATH*12]; + char *styles = NULL; struct charcache_s *c; float aspect = 1; enum fontfmt_e fmt = FMT_AUTO; @@ -2356,12 +2401,24 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal aspect = strtod(t, &t); parms = t; } + if (!strncmp(parms, "style=", 6)) + { + char *t = parms+6; + styles = t; + while (*t && *t != '&') + { + if (*t == ' ') + *t = ':'; + t++; + } + parms = t; + } while(*parms && *parms != '&') parms++; if (*parms == '&') { - parms++; + *parms++ = 0; continue; } } @@ -2547,7 +2604,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal else if (fmt == FMT_HORIZONTAL) success = Font_LoadHorizontalFont(f, height, start); #ifdef AVAIL_FREETYPE - else if (fmt == FMT_AUTO && Font_LoadFreeTypeFont(f, height, start)) + else if (fmt == FMT_AUTO && Font_LoadFreeTypeFont(f, height, start, styles)) success = true; #endif else