From 7f836eb389e904c52ef5759e6c565e9b605e4ef7 Mon Sep 17 00:00:00 2001 From: macallan Date: Wed, 11 Jan 2012 15:52:32 +0000 Subject: [PATCH] make rasops_init()'s font selection code a bit less boneheaded by: - actually trying to pick a font which gets as close as possible to the requested terminal size - accepting 0,0 as 'use system default' which can be changed by options RASOPS_DEFAULT_WIDTH=100 options RASOPS_DEFAULT_HEIGHT=30 default is 80x25 - putting alpha and bitmap fonts in the same list and making wsfont_find() aware of wether we support alpha fonts or not - if supported, prefer alpha fonts over otherwise equally suitable bitmap fonts --- sys/dev/rasops/files.rasops | 4 +- sys/dev/rasops/rasops.c | 107 +++++++++++++++++++++++++++++------- sys/dev/rasops/rasops.h | 3 +- sys/dev/wsfont/wsfont.c | 56 +++++++------------ sys/dev/wsfont/wsfont.h | 16 ++++-- 5 files changed, 125 insertions(+), 61 deletions(-) diff --git a/sys/dev/rasops/files.rasops b/sys/dev/rasops/files.rasops index 79351b38db84..208020fba43c 100644 --- a/sys/dev/rasops/files.rasops +++ b/sys/dev/rasops/files.rasops @@ -1,4 +1,4 @@ -# $NetBSD: files.rasops,v 1.12 2007/02/02 02:10:24 ober Exp $ +# $NetBSD: files.rasops,v 1.13 2012/01/11 15:52:32 macallan Exp $ # Note: `rasops_glue' is only here to force the header file's name # hence it must be mentioned first (shudder...) @@ -18,3 +18,5 @@ file dev/rasops/rasops24.c ((rasterconsole | wsdisplay) & rasops24) file dev/rasops/rasops32.c ((rasterconsole | wsdisplay) & rasops32) defflag opt_rasops.h RASOPS_CLIPPING RASOPS_SMALL +defparam opt_rasops.h RASOPS_DEFAULT_WIDTH = 80 +defparam opt_rasops.h RASOPS_DEFAULT_HEIGHT = 25 diff --git a/sys/dev/rasops/rasops.c b/sys/dev/rasops/rasops.c index 90d2012cf466..12964b704f14 100644 --- a/sys/dev/rasops/rasops.c +++ b/sys/dev/rasops/rasops.c @@ -1,4 +1,4 @@ -/* $NetBSD: rasops.c,v 1.69 2012/01/04 20:17:05 macallan Exp $ */ +/* $NetBSD: rasops.c,v 1.70 2012/01/11 15:52:32 macallan Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.69 2012/01/04 20:17:05 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.70 2012/01/11 15:52:32 macallan Exp $"); #include "opt_rasops.h" #include "rasops_glue.h" @@ -53,6 +53,20 @@ __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.69 2012/01/04 20:17:05 macallan Exp $") #include #endif +#ifdef RASOPS_DEBUG +#define DPRINTF aprint_error +#else +#define DPRINTF while (0) printf +#endif + +struct rasops_matchdata { + struct rasops_info *ri; + int wantcols, wantrows; + int bestscore; + struct wsdisplay_font *pick; + int ident; +}; + /* ANSI colormap (R,G,B). Upper 8 are high-intensity */ const u_char rasops_cmap[256*3] = { 0x00, 0x00, 0x00, /* black */ @@ -166,6 +180,57 @@ void rasops_make_box_chars_alpha(struct rasops_info *); extern int cold; +/* + * Rate a font based on how many character cells we would get out of it in the + * current video mode. Lower is better. + */ +static void +rasops_matches(struct wsdisplay_font *font, void *cookie, int ident) +{ + struct rasops_matchdata *md = cookie; + struct rasops_info *ri = md->ri; + int cols, score = 1; + + /* first weed out fonts the caller doesn't claim support for */ + if (FONT_IS_ALPHA(font)) { + /* + * If we end up with a bitmap font and an alpha font with + * otherwise identical scores, prefer alpha + */ + score = 0; + if ((ri->ri_flg & RI_ENABLE_ALPHA) == 0) + return; + } + cols = ri->ri_width / font->fontwidth; + /* + * if the font is too small to allow 80 columns give those closer to + * 80 a better score but with a huge penalty compared to fonts that + * give us 80 columns or more + */ + if (cols < md->wantcols) { + score += 100000 + 2 * (md->wantcols - cols); + } else + score += 2 * cols; + DPRINTF("%s: %d\n", font->name, score); + if (score < md->bestscore) { + md->bestscore = score; + md->pick = font; + md->ident = ident; + } +} + +static int +rasops_find(struct rasops_info *ri, int wantrows, int wantcols) +{ + struct rasops_matchdata md = + { ri, wantcols, wantrows, 1000000, NULL, 0}; + + wsfont_walk(rasops_matches, &md); + if (md.pick == NULL) + return -1; + return (wsfont_make_cookie(md.ident, WSDISPLAY_FONTORDER_L2R, + WSDISPLAY_FONTORDER_L2R)); +} /* * Initialize a 'rasops_info' descriptor. */ @@ -181,22 +246,21 @@ rasops_init(struct rasops_info *ri, int wantrows, int wantcols) wsfont_init(); - if (ri->ri_flg & RI_ENABLE_ALPHA) { - /* try finding an AA font first */ - cookie = wsfont_find_aa(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R, - WSDISPLAY_FONTORDER_L2R); - } - if (cookie == -1) { - /* Want 8 pixel wide, don't care about aesthetics */ - cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_L2R, - WSDISPLAY_FONTORDER_L2R); - } - if (cookie <= 0) - cookie = wsfont_find(NULL, 0, 0, 0, - WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R); + /* + * first, try to find something that's as close as possible + * to the caller's requested terminal size + */ + if (wantrows == 0) + wantrows = RASOPS_DEFAULT_HEIGHT; + if (wantcols == 0) + wantcols = RASOPS_DEFAULT_WIDTH; + cookie = rasops_find(ri, wantrows, wantcols); + /* + * this means there is no supported font in the list + */ if (cookie <= 0) { - printf("rasops_init: font table is empty\n"); + aprint_error("rasops_init: font table is empty\n"); return (-1); } @@ -214,7 +278,7 @@ rasops_init(struct rasops_info *ri, int wantrows, int wantcols) #endif if (wsfont_lock(cookie, &ri->ri_font)) { - printf("rasops_init: couldn't lock font\n"); + aprint_error("rasops_init: couldn't lock font\n"); return (-1); } @@ -225,12 +289,12 @@ rasops_init(struct rasops_info *ri, int wantrows, int wantcols) /* This should never happen in reality... */ #ifdef DEBUG if ((long)ri->ri_bits & 3) { - printf("rasops_init: bits not aligned on 32-bit boundary\n"); + aprint_error("rasops_init: bits not aligned on 32-bit boundary\n"); return (-1); } if ((int)ri->ri_stride & 3) { - printf("rasops_init: stride not aligned on 32-bit boundary\n"); + aprint_error("rasops_init: stride not aligned on 32-bit boundary\n"); return (-1); } #endif @@ -252,6 +316,11 @@ rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols) s = splhigh(); + if (wantrows == 0) + wantrows = RASOPS_DEFAULT_HEIGHT; + if (wantcols == 0) + wantcols = RASOPS_DEFAULT_WIDTH; + /* throw away old line drawing character bitmaps, if we have any */ if (ri->ri_optfont.data != NULL) { kmem_free(ri->ri_optfont.data, ri->ri_optfont.stride * diff --git a/sys/dev/rasops/rasops.h b/sys/dev/rasops/rasops.h index 805bb21fc0b1..db44bef23164 100644 --- a/sys/dev/rasops/rasops.h +++ b/sys/dev/rasops/rasops.h @@ -1,4 +1,4 @@ -/* $NetBSD: rasops.h,v 1.29 2012/01/03 23:13:59 macallan Exp $ */ +/* $NetBSD: rasops.h,v 1.30 2012/01/11 15:52:32 macallan Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -143,7 +143,6 @@ struct rasops_info { (ri->ri_optfont.data != NULL)) ? \ &ri->ri_optfont : ri->ri_font -#define FONT_IS_ALPHA(f) ((f)->fontwidth <= (f)->stride) /* * rasops_init(). * diff --git a/sys/dev/wsfont/wsfont.c b/sys/dev/wsfont/wsfont.c index 381ef2a15ff7..6d650b5f6d8a 100644 --- a/sys/dev/wsfont/wsfont.c +++ b/sys/dev/wsfont/wsfont.c @@ -1,4 +1,4 @@ -/* $NetBSD: wsfont.c,v 1.52 2011/12/28 18:29:48 macallan Exp $ */ +/* $NetBSD: wsfont.c,v 1.53 2012/01/11 15:52:32 macallan Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.52 2011/12/28 18:29:48 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.53 2012/01/11 15:52:32 macallan Exp $"); #include "opt_wsfont.h" @@ -131,7 +131,7 @@ __KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.52 2011/12/28 18:29:48 macallan Exp $") #include #endif -/* Make sure we always have at least one font. */ +/* Make sure we always have at least one bitmap font. */ #ifndef HAVE_FONT #define HAVE_FONT 1 #define FONT_BOLD8x16 1 @@ -211,9 +211,6 @@ static struct font builtin_fonts[] = { #ifdef FONT_OMRON12x20 { { NULL, NULL }, &omron12x20, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN }, #endif - { { NULL, NULL }, NULL, 0, 0, 0 }, -}; -static struct font builtin_aa_fonts[] = { #ifdef FONT_DEJAVU_SANS_MONO12x22 { { NULL, NULL }, &DejaVu_Sans_Mono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN }, #endif @@ -230,7 +227,6 @@ static struct font builtin_aa_fonts[] = { }; static TAILQ_HEAD(,font) list; -static TAILQ_HEAD(,font) aa_list; static int ident; /* Reverse the bit order in a byte */ @@ -273,9 +269,8 @@ static struct font *wsfont_find0(int, int); static struct font *wsfont_add0(struct wsdisplay_font *, int); static void wsfont_revbit(struct wsdisplay_font *); static void wsfont_revbyte(struct wsdisplay_font *); -static inline int wsfont_make_cookie(int, int, int); -static inline int +int wsfont_make_cookie(int cident, int bito, int byteo) { @@ -540,16 +535,6 @@ wsfont_init(void) ent->font->bitorder, ent->font->byteorder); TAILQ_INSERT_TAIL(&list, ent, chain); } - - TAILQ_INIT(&aa_list); - ent = builtin_aa_fonts; - - for (i = 0; builtin_aa_fonts[i].font != NULL; i++, ent++) { - ident += (1 << WSFONT_IDENT_SHIFT); - ent->cookie = wsfont_make_cookie(ident, - ent->font->bitorder, ent->font->byteorder); - TAILQ_INSERT_TAIL(&aa_list, ent, chain); - } } static struct font * @@ -562,19 +547,23 @@ wsfont_find0(int cookie, int mask) return (ent); } - TAILQ_FOREACH(ent, &aa_list, chain) { - if ((ent->cookie & mask) == (cookie & mask)) - return (ent); - } - return (NULL); } int wsfont_matches(struct wsdisplay_font *font, const char *name, - int width, int height, int stride) + int width, int height, int stride, int flags) { + /* first weed out fonts the caller doesn't claim support for */ + if (FONT_IS_ALPHA(font)) { + if ((flags & WSFONT_FIND_ALPHA) == 0) + return 0; + } else { + if ((flags & WSFONT_FIND_BITMAP) == 0) + return 0; + } + if (height != 0 && font->fontheight != height) return (0); @@ -591,29 +580,26 @@ wsfont_matches(struct wsdisplay_font *font, const char *name, } int -wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo) +wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags) { struct font *ent; TAILQ_FOREACH(ent, &list, chain) { - if (wsfont_matches(ent->font, name, width, height, stride)) + if (wsfont_matches(ent->font, name, width, height, stride, flags)) return (wsfont_make_cookie(ent->cookie, bito, byteo)); } return (-1); } -int -wsfont_find_aa(const char *name, int width, int height, int stride, int bito, int byteo) +void +wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie) { struct font *ent; - TAILQ_FOREACH(ent, &aa_list, chain) { - if (wsfont_matches(ent->font, name, width, height, stride)) - return (wsfont_make_cookie(ent->cookie, bito, byteo)); + TAILQ_FOREACH(ent, &list, chain) { + matchfunc(ent->font, cookie, ent->cookie); } - - return (-1); } static struct font * @@ -657,7 +643,7 @@ wsfont_add(struct wsdisplay_font *font, int copy) /* Don't allow exact duplicates */ if (wsfont_find(font->name, font->fontwidth, font->fontheight, - font->stride, 0, 0) >= 0) + font->stride, 0, 0, WSFONT_FIND_ALL) >= 0) return (EEXIST); ent = wsfont_add0(font, copy); diff --git a/sys/dev/wsfont/wsfont.h b/sys/dev/wsfont/wsfont.h index 46349010ad05..7b6639bf8e8d 100644 --- a/sys/dev/wsfont/wsfont.h +++ b/sys/dev/wsfont/wsfont.h @@ -1,4 +1,4 @@ -/* $NetBSD: wsfont.h,v 1.23 2012/01/04 15:53:49 macallan Exp $ */ +/* $NetBSD: wsfont.h,v 1.24 2012/01/11 15:52:32 macallan Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002 The NetBSD Foundation, Inc. @@ -36,6 +36,8 @@ #define WSFONT_FLAG_OPT 0x01000000 /* use alternate font */ #define WSFONT_GLYPH(c, font) ((uint8_t *)font->data + \ ((c) - font->firstchar) * font->stride * font->fontheight) +#define FONT_IS_ALPHA(f) ((f)->fontwidth <= (f)->stride) + /* * Example: * @@ -58,9 +60,13 @@ struct wsdisplay_font; void wsfont_init(void); -int wsfont_matches(struct wsdisplay_font *, const char *, int, int, int); -int wsfont_find(const char *, int, int, int, int, int); -int wsfont_find_aa(const char *, int, int, int, int, int); +int wsfont_matches(struct wsdisplay_font *, const char *, int, int, int, int); +int wsfont_find(const char *, int, int, int, int, int, int); +#define WSFONT_FIND_BITMAP 1 +#define WSFONT_FIND_ALPHA 2 +#define WSFONT_FIND_ALL 0xff +void wsfont_walk(void (*)(struct wsdisplay_font *, void *, int), void *); + int wsfont_add(struct wsdisplay_font *, int); int wsfont_remove(int); void wsfont_enum(void (*)(const char *, int, int, int)); @@ -75,4 +81,6 @@ enum { WSFONT_ROTATE_UD }; +int wsfont_make_cookie(int, int, int); + #endif /* !_WSFONT_H_ */