Linux console tools development discussion
 help / color / mirror / Atom feed
* [kbd] [PATCH] setfont: Add option -d to double size of font.
@ 2019-09-06  2:22 Ben Pfaff
  2019-09-17 13:31 ` Alexey Gladkov
  2019-09-26  8:33 ` Alexey Gladkov
  0 siblings, 2 replies; 5+ messages in thread
From: Ben Pfaff @ 2019-09-06  2:22 UTC (permalink / raw)
  To: kbd; +Cc: Ben Pfaff

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 <blp@cs.stanford.edu>
---
 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<N>      (no space) Override font height.\n"
+	                    "    -d         Double size of font horizontally and vertically.\n"
 	                    "    -m <fn>    Load console screen map.\n"
 	                    "    -u <fn>    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



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-09-27 14:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-06  2:22 [kbd] [PATCH] setfont: Add option -d to double size of font Ben Pfaff
2019-09-17 13:31 ` Alexey Gladkov
2019-09-18 14:54   ` Ben Pfaff
2019-09-26  8:33 ` Alexey Gladkov
2019-09-27 14:41   ` Ben Pfaff

Linux console tools development discussion

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/kbd/0 kbd/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 kbd kbd/ http://lore.altlinux.org/kbd \
		kbd@lists.altlinux.org kbd@lists.altlinux.ru kbd@lists.altlinux.com
	public-inbox-index kbd

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.kbd


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git