From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on sa.local.altlinux.org X-Spam-Level: X-Spam-Status: No, score=-3.3 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD autolearn=ham autolearn_force=no version=3.4.1 From: Ben Pfaff To: kbd@lists.altlinux.org Date: Thu, 5 Sep 2019 19:22:35 -0700 Message-Id: <20190906022235.30572-1-blp@cs.stanford.edu> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scan-Signature: f5e9e554c6b25ad025467fa91158a833 X-Mailman-Approved-At: Fri, 06 Sep 2019 10:51:53 +0300 Cc: Ben Pfaff Subject: [kbd] [PATCH] setfont: Add option -d to double size of font. X-BeenThere: kbd@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: Linux console tools development discussion List-Id: Linux console tools development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Sep 2019 02:22:55 -0000 Archived-At: List-Archive: On high pixel density systems, such as 4k displays, typical font sizes like 8x16 are illegible to most readers. One solution would be to install and use fonts that are designed for these displays, but currently these are not widely available and perhaps they will never be available in all the same varieties as the low-density fonts that have been used for a long time. This patch introduces an alternative: it implements a -d option to setfont that causes each pixel to be doubled along each axis (which actually quadruples the size of the font). It makes all of the traditional fonts usable on high-DPI display. Signed-off-by: Ben Pfaff --- docs/man/man8/setfont.8.in | 7 ++++ src/setfont.c | 65 +++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/docs/man/man8/setfont.8.in b/docs/man/man8/setfont.8.in index 5ae63dd7cd67..e0e4bed8fb0d 100644 --- a/docs/man/man8/setfont.8.in +++ b/docs/man/man8/setfont.8.in @@ -183,6 +183,13 @@ One may add a Unicode mapping table to a psf font using .BI "\-h " H Override font height. .TP +.B \-d +Doubles the size of the font, by replicating all of its pixels +vertically and horizontally. This is suitable for high pixel density +(e.g. "4k") displays on which the standard fonts are too small to be +easily legible. Due to kernel limitations, this is suitable only for +16x16 or smaller fonts. +.TP .BI "\-m " file Load console map or Unicode console map from .IR file . diff --git a/src/setfont.c b/src/setfont.c index 3e21e7c99723..bcdb4e8bf7ad 100644 --- a/src/setfont.c +++ b/src/setfont.c @@ -47,9 +47,10 @@ extern void loadnewmap(int fd, char *mfil); extern void activatemap(int fd); extern void disactivatemap(int fd); -int verbose = 0; -int force = 0; -int debug = 0; +int verbose = 0; +int force = 0; +int debug = 0; +int double_size = 0; /* search for the font in these directories (with trailing /) */ const char *const fontdirpath[] = { "", DATADIR "/" FONTDIR "/", 0 }; @@ -89,6 +90,7 @@ usage(void) "Explicitly (with -m or -u) or implicitly (in the fontfile) given mappings\n" "will be loaded and, in the case of consolemaps, activated.\n" " -h (no space) Override font height.\n" + " -d Double size of font horizontally and vertically.\n" " -m Load console screen map.\n" " -u Load font unicode map.\n" " -m none Suppress loading and activation of a screen map.\n" @@ -168,6 +170,8 @@ int main(int argc, char *argv[]) hwunit = atoi(argv[i] + 2); if (hwunit <= 0 || hwunit > 32) usage(); + } else if (!strcmp(argv[i], "-d")) { + double_size = 1; } else if (argv[i][0] == '-') { iunit = atoi(argv[i] + 1); if (iunit <= 0 || iunit > 32) @@ -251,9 +255,7 @@ do_loadfont(int fd, char *inbuf, int width, int height, int hwunit, { unsigned char *buf; int i, buflen; - int bytewidth = (width + 7) / 8; - int charsize = height * bytewidth; - int kcharsize = 32 * bytewidth; + int kcharsize; int bad_video_erase_char = 0; if (height < 1 || height > 32) { @@ -268,12 +270,53 @@ do_loadfont(int fd, char *inbuf, int width, int height, int hwunit, if (!hwunit) hwunit = height; - buflen = kcharsize * ((fontsize < 128) ? 128 : fontsize); - buf = xmalloc(buflen); - memset(buf, 0, buflen); + if (double_size && (height > 16 || width > 16)) { + fprintf(stderr, _("Cannot double %dx%d font (limit is 16x16)"), + width, height); + double_size = 0; + } - for (i = 0; i < fontsize; i++) - memcpy(buf + (i * kcharsize), inbuf + (i * charsize), charsize); + if (double_size) { + int bytewidth = (width + 7) / 8; + int kbytewidth = (2 * width + 7) / 8; + int charsize = height * bytewidth; + kcharsize = 32 * kbytewidth; + buflen = kcharsize * ((fontsize < 128) ? 128 : fontsize); + buf = xmalloc(buflen); + memset(buf, 0, buflen); + + const unsigned char *src = (unsigned char *)inbuf; + for (i = 0; i < fontsize; i++) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < kbytewidth; x++) { + unsigned char b = src[i * charsize + y * bytewidth + x / 2]; + if (!(x & 1)) + b >>= 4; + + unsigned char b2 = 0; + for (int j = 0; j < 4; j++) + if (b & (1 << j)) + b2 |= 3 << (j * 2); + buf[i * kcharsize + (y * 2) * kbytewidth + x] = b2; + buf[i * kcharsize + ((y * 2) + 1) * kbytewidth + x] = b2; + } + } + } + + width *= 2; + height *= 2; + hwunit *= 2; + } else { + int bytewidth = (width + 7) / 8; + int charsize = height * bytewidth; + kcharsize = 32 * bytewidth; + buflen = kcharsize * ((fontsize < 128) ? 128 : fontsize); + buf = xmalloc(buflen); + memset(buf, 0, buflen); + + for (i = 0; i < fontsize; i++) + memcpy(buf + (i * kcharsize), inbuf + (i * charsize), charsize); + } /* * Due to a kernel bug, font position 32 is used -- 2.20.1