1
0
Fork 0
forked from fte/fteqw

Eukara expressed an interest in loading fonts without any antialiasing.

This commit is contained in:
Shpoike 2023-02-11 05:01:56 +00:00
parent 73f9cddcdf
commit 0d2a0c615a
6 changed files with 127 additions and 38 deletions

View file

@ -105,6 +105,7 @@ struct {
char facename[MAX_OSPATH]; char facename[MAX_OSPATH];
float scale; //poop float scale; //poop
int outline; //argh int outline; //argh
unsigned int fontflags; //erk
int sizes; int sizes;
int size[FONT_SIZES]; int size[FONT_SIZES];
struct font_s *font[FONT_SIZES]; struct font_s *font[FONT_SIZES];
@ -233,7 +234,7 @@ void PR_ReloadFonts(qboolean reload)
{ //otherwise load it. { //otherwise load it.
for (j = 0; j < fontslot[i].sizes; j++) for (j = 0; j < fontslot[i].sizes; j++)
{ {
fontslot[i].font[j] = Font_LoadFont(fontslot[i].facename, fontslot[i].size[j], fontslot[i].scale, fontslot[i].outline); fontslot[i].font[j] = Font_LoadFont(fontslot[i].facename, fontslot[i].size[j], fontslot[i].scale, fontslot[i].outline, fontslot[i].fontflags);
} }
} }
} }
@ -333,7 +334,7 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if (qrenderer > QR_NONE) if (qrenderer > QR_NONE)
{ {
for (i = 0; i < fontslot[slotnum].sizes; i++) for (i = 0; i < fontslot[slotnum].sizes; i++)
fontslot[slotnum].font[i] = Font_LoadFont(facename, fontslot[slotnum].size[i], fontslot[slotnum].scale, fontslot[slotnum].outline); fontslot[slotnum].font[i] = Font_LoadFont(facename, fontslot[slotnum].size[i], fontslot[slotnum].scale, fontslot[slotnum].outline, fontslot[slotnum].fontflags);
} }
G_FLOAT(OFS_RETURN) = slotnum; G_FLOAT(OFS_RETURN) = slotnum;
@ -342,7 +343,7 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
void CL_LoadFont_f(void) void CL_LoadFont_f(void)
{ {
extern cvar_t r_font_postprocess_outline; extern cvar_t r_font_postprocess_outline, r_font_postprocess_mono;
//console command for compat with dp/debug. //console command for compat with dp/debug.
if (Cmd_Argc() == 1) if (Cmd_Argc() == 1)
{ {
@ -418,6 +419,8 @@ void CL_LoadFont_f(void)
fontslot[slotnum].scale = 1; fontslot[slotnum].scale = 1;
fontslot[slotnum].sizes = 0; fontslot[slotnum].sizes = 0;
fontslot[slotnum].outline = r_font_postprocess_outline.ival; //locked in at definition, so different fonts can have different settings even with vid_reload going on. fontslot[slotnum].outline = r_font_postprocess_outline.ival; //locked in at definition, so different fonts can have different settings even with vid_reload going on.
fontslot[slotnum].fontflags = 0 |
(r_font_postprocess_mono.ival?FONT_MONO:0);
} }
if (!*facename) if (!*facename)
return; return;
@ -437,6 +440,14 @@ void CL_LoadFont_f(void)
fontslot[slotnum].outline = atoi(Cmd_Argv(sizenum++)); fontslot[slotnum].outline = atoi(Cmd_Argv(sizenum++));
continue; continue;
} }
if (!strcmp(a, "mono"))
{
if (atoi(Cmd_Argv(sizenum++)))
fontslot[slotnum].fontflags |= FONT_MONO;
else
fontslot[slotnum].fontflags &= ~FONT_MONO;
continue;
}
if (!strcmp(a, "blur")) if (!strcmp(a, "blur"))
{ {
//fontslot[slotnum].blur = atoi(Cmd_Argv(sizenum++)); //fontslot[slotnum].blur = atoi(Cmd_Argv(sizenum++));
@ -471,7 +482,7 @@ void CL_LoadFont_f(void)
if (qrenderer > QR_NONE) if (qrenderer > QR_NONE)
{ {
for (i = 0; i < fontslot[slotnum].sizes; i++) for (i = 0; i < fontslot[slotnum].sizes; i++)
fontslot[slotnum].font[i] = Font_LoadFont(facename, fontslot[slotnum].size[i], fontslot[slotnum].scale, fontslot[slotnum].outline); fontslot[slotnum].font[i] = Font_LoadFont(facename, fontslot[slotnum].size[i], fontslot[slotnum].scale, fontslot[slotnum].outline, fontslot[slotnum].fontflags);
} }
//FIXME: slotnum0==default is problematic. //FIXME: slotnum0==default is problematic.

View file

@ -56,7 +56,7 @@ struct
extern cvar_t scr_conalpha; extern cvar_t scr_conalpha;
extern cvar_t gl_conback; extern cvar_t gl_conback;
extern cvar_t gl_font, con_textfont; extern cvar_t gl_font, con_textfont;
extern cvar_t r_font_postprocess_outline; extern cvar_t r_font_postprocess_outline, r_font_postprocess_mono;
extern cvar_t gl_screenangle; extern cvar_t gl_screenangle;
extern cvar_t vid_minsize; extern cvar_t vid_minsize;
extern cvar_t vid_conautoscale; extern cvar_t vid_conautoscale;
@ -167,6 +167,7 @@ void R2D_Shutdown(void)
Cvar_Unhook(&con_textfont); Cvar_Unhook(&con_textfont);
Cvar_Unhook(&gl_font); Cvar_Unhook(&gl_font);
Cvar_Unhook(&r_font_postprocess_outline); Cvar_Unhook(&r_font_postprocess_outline);
Cvar_Unhook(&r_font_postprocess_mono);
Cvar_Unhook(&vid_conautoscale); Cvar_Unhook(&vid_conautoscale);
Cvar_Unhook(&gl_screenangle); Cvar_Unhook(&gl_screenangle);
Cvar_Unhook(&vid_conheight); Cvar_Unhook(&vid_conheight);
@ -444,6 +445,7 @@ void R2D_Init(void)
Cvar_Hook(&con_textfont, R2D_Font_Callback); Cvar_Hook(&con_textfont, R2D_Font_Callback);
Cvar_Hook(&gl_font, R2D_Font_Callback); Cvar_Hook(&gl_font, R2D_Font_Callback);
Cvar_Hook(&r_font_postprocess_outline, R2D_Font_Callback); Cvar_Hook(&r_font_postprocess_outline, R2D_Font_Callback);
Cvar_Hook(&r_font_postprocess_mono, R2D_Font_Callback);
Cvar_Hook(&vid_conautoscale, R2D_Conautoscale_Callback); Cvar_Hook(&vid_conautoscale, R2D_Conautoscale_Callback);
Cvar_Hook(&gl_screenangle, R2D_ScreenAngle_Callback); Cvar_Hook(&gl_screenangle, R2D_ScreenAngle_Callback);
Cvar_Hook(&vid_conheight, R2D_Conheight_Callback); Cvar_Hook(&vid_conheight, R2D_Conheight_Callback);
@ -1137,6 +1139,7 @@ void R2D_Font_Changed(void)
{ {
float tsize; float tsize;
const char *con_font_name = con_textfont.string; const char *con_font_name = con_textfont.string;
unsigned int flags;
if (!con_textsize.modified) if (!con_textsize.modified)
return; return;
if (!*con_font_name) if (!*con_font_name)
@ -1170,6 +1173,10 @@ void R2D_Font_Changed(void)
if (qrenderer == QR_NONE) if (qrenderer == QR_NONE)
return; return;
flags = 0;
if (r_font_postprocess_mono.ival)
flags |= FONT_MONO;
if (!strcmp(gl_font.string, "?")) if (!strcmp(gl_font.string, "?"))
{ {
#ifndef AVAIL_FREETYPE #ifndef AVAIL_FREETYPE
@ -1184,9 +1191,9 @@ void R2D_Font_Changed(void)
LOGFONTW lf = {0}; LOGFONTW lf = {0};
CHOOSEFONTW cf = {sizeof(cf)}; CHOOSEFONTW cf = {sizeof(cf)};
extern HWND mainwindow; extern HWND mainwindow;
font_default = Font_LoadFont("", 8, 1, r_font_postprocess_outline.ival); font_default = Font_LoadFont("", 8, 1, r_font_postprocess_outline.ival, flags);
if (tsize != 8) if (tsize != 8)
font_console = Font_LoadFont("", tsize, 1, r_font_postprocess_outline.ival); font_console = Font_LoadFont("", tsize, 1, r_font_postprocess_outline.ival, flags);
if (!font_console) if (!font_console)
font_console = font_default; font_console = font_default;
@ -1230,19 +1237,19 @@ void R2D_Font_Changed(void)
} }
if (COM_FCheckExists("fonts/qfont.kfont")) if (COM_FCheckExists("fonts/qfont.kfont"))
font_menu = Font_LoadFont("qfont", 20, 1, r_font_postprocess_outline.ival); font_menu = Font_LoadFont("qfont", 20, 1, r_font_postprocess_outline.ival, flags);
else else
font_menu = NULL; font_menu = NULL;
font_default = Font_LoadFont(gl_font.string, 8, 1, r_font_postprocess_outline.ival); font_default = Font_LoadFont(gl_font.string, 8, 1, r_font_postprocess_outline.ival, flags);
if (!font_default && *gl_font.string) if (!font_default && *gl_font.string)
font_default = Font_LoadFont("", 8, 1, r_font_postprocess_outline.ival); font_default = Font_LoadFont("", 8, 1, r_font_postprocess_outline.ival, flags);
if (tsize != 8 || strcmp(gl_font.string, con_font_name)) if (tsize != 8 || strcmp(gl_font.string, con_font_name))
{ {
font_console = Font_LoadFont(con_font_name, tsize, 1, r_font_postprocess_outline.ival); font_console = Font_LoadFont(con_font_name, tsize, 1, r_font_postprocess_outline.ival, flags);
if (!font_console) if (!font_console)
font_console = Font_LoadFont("", tsize, 1, r_font_postprocess_outline.ival); font_console = Font_LoadFont("", tsize, 1, r_font_postprocess_outline.ival, flags);
} }
if (!font_console) if (!font_console)
font_console = font_default; font_console = font_default;

View file

@ -458,6 +458,7 @@ cvar_t gl_texturemode2d = CVARFCD("gl_texturemode2d", "GL_LINEAR",
"Specifies how 2d images are sampled. format is a 3-tupple "); "Specifies how 2d images are sampled. format is a 3-tupple ");
cvar_t r_font_linear = CVARF("r_font_linear", "1", CVAR_ARCHIVE); cvar_t r_font_linear = CVARF("r_font_linear", "1", CVAR_ARCHIVE);
cvar_t r_font_postprocess_outline = CVARFD("r_font_postprocess_outline", "0", 0, "Controls the number of pixels of dark borders to use around fonts."); cvar_t r_font_postprocess_outline = CVARFD("r_font_postprocess_outline", "0", 0, "Controls the number of pixels of dark borders to use around fonts.");
cvar_t r_font_postprocess_mono = CVARFD("r_font_postprocess_mono", "0", 0, "Disables anti-aliasing on fonts.");
#if defined(HAVE_LEGACY) && defined(AVAIL_FREETYPE) #if defined(HAVE_LEGACY) && defined(AVAIL_FREETYPE)
cvar_t dpcompat_smallerfonts = CVARFD("dpcompat_smallerfonts", "0", 0, "Mimics DP's behaviour of using a smaller font size than was actually requested."); cvar_t dpcompat_smallerfonts = CVARFD("dpcompat_smallerfonts", "0", 0, "Mimics DP's behaviour of using a smaller font size than was actually requested.");
@ -984,6 +985,7 @@ void Renderer_Init(void)
Cvar_Register (&gl_texturemode2d, GLRENDEREROPTIONS); Cvar_Register (&gl_texturemode2d, GLRENDEREROPTIONS);
Cvar_Register (&r_font_linear, GLRENDEREROPTIONS); Cvar_Register (&r_font_linear, GLRENDEREROPTIONS);
Cvar_Register (&r_font_postprocess_outline, GLRENDEREROPTIONS); Cvar_Register (&r_font_postprocess_outline, GLRENDEREROPTIONS);
Cvar_Register (&r_font_postprocess_mono, GLRENDEREROPTIONS);
#if defined(HAVE_LEGACY) && defined(AVAIL_FREETYPE) #if defined(HAVE_LEGACY) && defined(AVAIL_FREETYPE)
Cvar_Register (&dpcompat_smallerfonts, GLRENDEREROPTIONS); Cvar_Register (&dpcompat_smallerfonts, GLRENDEREROPTIONS);
#endif #endif

View file

@ -1279,7 +1279,7 @@ void Draw_TinyString (float x, float y, const qbyte *str)
if (!font_tiny) if (!font_tiny)
{ {
font_tiny = Font_LoadFont("gfx/tinyfont", 8, 1, 0); font_tiny = Font_LoadFont("gfx/tinyfont", 8, 1, 0, 0);
if (!font_tiny) if (!font_tiny)
return; return;
} }

View file

@ -321,7 +321,8 @@ void Font_Init(void);
void Font_Shutdown(void); void Font_Shutdown(void);
int Font_RegisterTrackerImage(const char *image); //returns a unicode char value that can be used to embed the char within a line of text. int Font_RegisterTrackerImage(const char *image); //returns a unicode char value that can be used to embed the char within a line of text.
qboolean Font_TrackerValid(unsigned int imid); qboolean Font_TrackerValid(unsigned int imid);
struct font_s *Font_LoadFont(const char *fontfilename, float height, float scale, int outline); struct font_s *Font_LoadFont(const char *fontfilename, float height, float scale, int outline, unsigned int flags);
#define FONT_MONO 1
void Font_Free(struct font_s *f); void Font_Free(struct font_s *f);
void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py); void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py);
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py); /*avoid using*/ void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py); /*avoid using*/

View file

@ -15,7 +15,7 @@
void Font_Init(void); void Font_Init(void);
void Font_Shutdown(void); void Font_Shutdown(void);
struct font_s *Font_LoadFont(const char *fontfilename, float height, float scale, int outline); struct font_s *Font_LoadFont(const char *fontfilename, float height, float scale, int outline, unsigned int flags);
void Font_Free(struct font_s *f); void Font_Free(struct font_s *f);
void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py); void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py);
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py); /*avoid using*/ void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py); /*avoid using*/
@ -80,6 +80,9 @@ const char *(VARGS *pFT_Error_String) (FT_Error error_code);
typedef unsigned int FT_Pixel_Mode; //for consistency even without freetype support. typedef unsigned int FT_Pixel_Mode; //for consistency even without freetype support.
#endif #endif
#ifndef FT_PIXEL_MODE_MONO
#define FT_PIXEL_MODE_MONO 1
#endif
#ifndef FT_PIXEL_MODE_GRAY #ifndef FT_PIXEL_MODE_GRAY
#define FT_PIXEL_MODE_GRAY 2 #define FT_PIXEL_MODE_GRAY 2
#endif #endif
@ -322,6 +325,7 @@ typedef struct font_s
unsigned short truecharheight; //what you actually got, for compat with dp's lets-use-the-wrong-size-for-double-padding-between-lines thing. unsigned short truecharheight; //what you actually got, for compat with dp's lets-use-the-wrong-size-for-double-padding-between-lines thing.
float scale; //some sort of poop float scale; //some sort of poop
short outline; short outline;
unsigned int flags;
unsigned short faces; unsigned short faces;
fontface_t *face[MAX_FACES]; fontface_t *face[MAX_FACES];
@ -721,6 +725,32 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
out += PLANEWIDTH; out += PLANEWIDTH;
} }
} }
else if (pixelmode == FT_PIXEL_MODE_MONO)
{ //1bit font (
for (y = -pad; y < 0; y++)
{
for (x = -pad; x < (int)bmw+pad; x++)
out[x].c = BORDERCOLOUR;
out += PLANEWIDTH;
}
for (; y < bmh; y++)
{
for (x = -pad; x < 0; x++)
out[x].c = BORDERCOLOUR;
for (; x < bmw; x++)
out[x].c = (((unsigned char*)data)[x>>3]&(1<<(7-(x&7))))?0xffffffff:0;
for (; x < bmw+pad; x++)
out[x].c = BORDERCOLOUR;
data = (char*)data + pitch;
out += PLANEWIDTH;
}
for (; y < bmh+pad; y++)
{
for (x = -pad; x < (int)bmw+pad; x++)
out[x].c = BORDERCOLOUR;
out += PLANEWIDTH;
}
}
else if ((unsigned int)pixelmode == FT_PIXEL_MODE_RGBA_SA) else if ((unsigned int)pixelmode == FT_PIXEL_MODE_RGBA_SA)
{ //rgba source using standard alpha. { //rgba source using standard alpha.
//(we'll multiply out the alpha for the gpu) //(we'll multiply out the alpha for the gpu)
@ -822,9 +852,6 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
if (outline) if (outline)
{ {
int bytes = (pixelmode == FT_PIXEL_MODE_GRAY)?1:4;
qbyte *alpha = (char*)data + bytes-1 - pitch*bmh;
static int filter_outline; static int filter_outline;
static unsigned char filter_highest[MAXOUTLINE*2+1][MAXOUTLINE*2+1]; static unsigned char filter_highest[MAXOUTLINE*2+1][MAXOUTLINE*2+1];
if (outline != filter_outline) if (outline != filter_outline)
@ -837,6 +864,39 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
//expand it to out full(ish) size //expand it to out full(ish) size
if (pixelmode == FT_PIXEL_MODE_MONO)
{
qbyte *alpha = (char*)data - pitch*bmh;
qbyte a;
int bit;
alpha -= pitch*outline;
out = &fontplanes.plane[c->bmx+((int)c->bmy-outline)*PLANEHEIGHT];
for (y = -outline; y < (int)bmh+outline; y++, out += PLANEWIDTH)
for (x = -outline; x < (int)bmw+outline; x++)
{
int xn, x1 = max(outline-x, 0), x2 = min(2*outline, (int)bmw-1-x+outline);
int yn, y1 = max(outline-y, 0), y2 = min(2*outline, (int)bmh-1-y+outline);
int v, m = out[x].rgba[3]*255;
for (yn = y1; yn <= y2; yn++)
for (xn = x1; xn <= x2; xn++)
{
bit = (xn+x)-outline;
a = alpha[(bit>>3)+(yn+y)*pitch];
a = (a&(1<<(7-(bit&7))))?0xff:0;
v = filter_highest[yn][xn] * a;
m = max(m, v);
}
//out[x].c = 0;
out[x].rgba[3] = m/255;
}
}
else
{
int bytes = (pixelmode == FT_PIXEL_MODE_GRAY)?1:4;
qbyte *alpha = (char*)data + bytes-1 - pitch*bmh;
alpha -= pitch*outline + bytes*outline; alpha -= pitch*outline + bytes*outline;
out = &fontplanes.plane[c->bmx+((int)c->bmy-outline)*PLANEHEIGHT]; out = &fontplanes.plane[c->bmx+((int)c->bmy-outline)*PLANEHEIGHT];
for (y = -outline; y < (int)bmh+outline; y++, out += PLANEWIDTH) for (y = -outline; y < (int)bmh+outline; y++, out += PLANEWIDTH)
@ -854,6 +914,7 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
//out[x].c = 0; //out[x].c = 0;
out[x].rgba[3] = m/255; out[x].rgba[3] = m/255;
} }
}
c->bmx -= outline; c->bmx -= outline;
@ -1317,7 +1378,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
return NULL; //some sort of error. return NULL; //some sort of error.
} }
if (charidx == 0xfffe || pFT_Get_Char_Index(face, charidx)) //ignore glyph 0 (undefined) if (charidx == 0xfffe || pFT_Get_Char_Index(face, charidx)) //ignore glyph 0 (undefined)
if (pFT_Load_Char(face, charidx, FT_LOAD_RENDER|FT_LOAD_COLOR) == 0) if (pFT_Load_Char(face, charidx, FT_LOAD_RENDER|(((f->flags&FONT_MONO)&&qface->ft.activeheight==qface->ft.actualsize/*FIXME*/)?FT_LOAD_TARGET_MONO:FT_LOAD_TARGET_NORMAL)|FT_LOAD_COLOR) == 0)
{ {
FT_GlyphSlot slot; FT_GlyphSlot slot;
FT_Bitmap *bm; FT_Bitmap *bm;
@ -1349,6 +1410,12 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
Image_ResampleTexture(PTI_L8, (void*)bm->buffer, bm->width, bm->rows, out, nw, nh); Image_ResampleTexture(PTI_L8, (void*)bm->buffer, bm->width, bm->rows, out, nw, nh);
c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, out, nw, nh, nw*sizeof(*out)); c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, out, nw, nh, nw*sizeof(*out));
} }
/*else if (bm->pixel_mode == FT_PIXEL_MODE_MONO)
{
unsigned char *out = alloca(nw*nh*sizeof(*out));
Image_ResampleTexture(PTI_L1, (void*)bm->buffer, bm->width, bm->rows, out, nw, nh);
c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, out, nw, nh, nw*sizeof(*out));
}*/
else else
c = NULL; c = NULL;
if (c) if (c)
@ -2209,7 +2276,7 @@ static qboolean Font_LoadFontLump(font_t *f, const char *facename)
//creates a new font object from the given file, with each text row with the given height. //creates a new font object from the given file, with each text row with the given height.
//width is implicit and scales with height and choice of font. //width is implicit and scales with height and choice of font.
struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scale, int outline) struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scale, int outline, unsigned int flags)
{ {
struct font_s *f; struct font_s *f;
int i = 0; int i = 0;
@ -2237,6 +2304,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
f->scale = scale; f->scale = scale;
f->charheight = height; f->charheight = height;
f->truecharheight = height; f->truecharheight = height;
f->flags = flags;
Q_strncpyz(f->name, fontfilename, sizeof(f->name)); Q_strncpyz(f->name, fontfilename, sizeof(f->name));
switch(M_GameType()) switch(M_GameType())
@ -2454,7 +2522,7 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
} }
else else
{ {
f->alt = Font_LoadFont(aname, vheight, scale, outline); f->alt = Font_LoadFont(aname, vheight, scale, outline, flags);
if (f->alt) if (f->alt)
{ {
VectorCopy(f->alt->tint, f->alttint); VectorCopy(f->alt->tint, f->alttint);