Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Jun 2014 18:38:28 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r267123 - head/tools/tools/vt/fontcvt
Message-ID:  <201406051838.s55IcSJT014710@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Thu Jun  5 18:38:27 2014
New Revision: 267123
URL: http://svnweb.freebsd.org/changeset/base/267123

Log:
  Support "GNU Unifont" format font data
  
  The GNU Unifont .hex format is a text file.  Each line represents one
  glyph and consists of a four-digit hex code point, a colon, and pairs of
  hex digits representing the bitmap.  By default an 8x16 font is assumed,
  with 16x16 double-width glyphs, resulting in either 32 or 64 hex digits
  for the bitmap.
  
  Our version of the file format supports comments at the top of the file
  to set the height and width:
  
  # Height: <decimal height>
  # Width: <decimal width>
  
  Each row of bitmap data is rounded up to byte width - for example, a
  10-pixel wide font uses 4 characters per row.
  
  See http://czyborra.com/unifont/ for more background on the original
  format.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/tools/tools/vt/fontcvt/fontcvt.c

Modified: head/tools/tools/vt/fontcvt/fontcvt.c
==============================================================================
--- head/tools/tools/vt/fontcvt/fontcvt.c	Thu Jun  5 18:23:51 2014	(r267122)
+++ head/tools/tools/vt/fontcvt/fontcvt.c	Thu Jun  5 18:38:27 2014	(r267123)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009 The FreeBSD Foundation
+ * Copyright (c) 2009, 2014 The FreeBSD Foundation
  * All rights reserved.
  *
  * This software was developed by Ed Schouten under sponsorship from the
@@ -179,6 +179,30 @@ add_glyph(const uint8_t *bytes, unsigned
 }
 
 static int
+add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r)
+{
+	struct glyph *gl;
+
+	/* Prevent adding two glyphs for 0xFFFD */
+	if (curchar == 0xFFFD) {
+		if (map_idx < VFNT_MAP_BOLD)
+			gl = add_glyph(bytes, 0, 1);
+	} else if (curchar >= 0x20) {
+		gl = add_glyph(bytes, map_idx, 0);
+		if (add_mapping(gl, curchar, map_idx) != 0)
+			return (1);
+		if (bytes_r != NULL) {
+			gl = add_glyph(bytes_r, map_idx + 1, 0);
+			if (add_mapping(gl, curchar,
+			    map_idx + 1) != 0)
+				return (1);
+		}
+	}
+	return (0);
+}
+
+
+static int
 parse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line,
     unsigned int dwidth)
 {
@@ -218,20 +242,12 @@ parse_bitmap_line(uint8_t *left, uint8_t
 }
 
 static int
-parse_bdf(const char *filename, unsigned int map_idx)
+parse_bdf(FILE *fp, unsigned int map_idx)
 {
-	FILE *fp;
 	char *ln;
 	size_t length;
 	uint8_t bytes[wbytes * height], bytes_r[wbytes * height];
 	unsigned int curchar = 0, dwidth = 0, i, line;
-	struct glyph *gl;
-
-	fp = fopen(filename, "r");
-	if (fp == NULL) {
-		perror(filename);
-		return (1);
-	}
 
 	while ((ln = fgetln(fp, &length)) != NULL) {
 		ln[length - 1] = '\0';
@@ -257,27 +273,73 @@ parse_bdf(const char *filename, unsigned
 					return (1);
 			}
 
-			/* Prevent adding two glyphs for 0xFFFD */
-			if (curchar == 0xFFFD) {
-				if (map_idx < VFNT_MAP_BOLD)
-					gl = add_glyph(bytes, 0, 1);
-			} else if (curchar >= 0x20) {
-				gl = add_glyph(bytes, map_idx, 0);
-				if (add_mapping(gl, curchar, map_idx) != 0)
+			if (add_char(curchar, map_idx, bytes,
+			    dwidth == width * 2 ? bytes_r : NULL) != 0)
+				return (1);
+		}
+	}
+
+	return (0);
+}
+
+static int
+parse_hex(FILE *fp, unsigned int map_idx)
+{
+	char *ln, *p;
+	char fmt_str[8];
+	size_t length;
+	uint8_t bytes[wbytes * height], bytes_r[wbytes * height];
+	unsigned curchar = 0, i, line, chars_per_row, dwidth;
+
+	while ((ln = fgetln(fp, &length)) != NULL) {
+		ln[length - 1] = '\0';
+
+		if (strncmp(ln, "# Height: ", 10) == 0) {
+			height = atoi(ln + 10);
+		} else if (strncmp(ln, "# Width: ", 9) == 0) {
+			width = atoi(ln + 9);
+		} else if (sscanf(ln, "%4x:", &curchar)) {
+			p = ln + 5;
+			chars_per_row = strlen(p) / height;
+			dwidth = width;
+			if (chars_per_row / 2 > width / 8)
+				dwidth *= 2; /* Double-width character. */
+			snprintf(fmt_str, sizeof(fmt_str), "%%%ux",
+			    chars_per_row);
+			
+			for (i = 0; i < height; i++) {
+				sscanf(p, fmt_str, &line);
+				p += chars_per_row;
+				if (parse_bitmap_line(bytes + i * wbytes,
+				    bytes_r + i * wbytes, line, dwidth) != 0)
 					return (1);
-				if (dwidth == width * 2) {
-					gl = add_glyph(bytes_r, map_idx + 1, 0);
-					if (add_mapping(gl, curchar,
-					    map_idx + 1) != 0)
-						return (1);
-				}
 			}
+
+			if (add_char(curchar, map_idx, bytes,
+			    dwidth == width * 2 ? bytes_r : NULL) != 0)
+				return (1);
 		}
 	}
-
 	return (0);
 }
 
+static int
+parse_file(const char *filename, unsigned int map_idx)
+{
+	FILE *fp;
+	size_t len;
+
+	fp = fopen(filename, "r");
+	if (fp == NULL) {
+		perror(filename);
+		return (1);
+	}
+	len = strlen(filename);
+	if (len > 4 && strcasecmp(filename + len - 4, ".hex") == 0)
+		return parse_hex(fp, map_idx);
+	return parse_bdf(fp, map_idx);
+}
+
 static void
 number_glyphs(void)
 {
@@ -416,12 +478,12 @@ main(int argc, char *argv[])
 
 	wbytes = howmany(width, 8);
 
-	if (parse_bdf(argv[0], VFNT_MAP_NORMAL) != 0)
+	if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0)
 		return (1);
 	argc--;
 	argv++;
 	if (argc == 2) {
-		if (parse_bdf(argv[0], VFNT_MAP_BOLD) != 0)
+		if (parse_file(argv[0], VFNT_MAP_BOLD) != 0)
 			return (1);
 		argc--;
 		argv++;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406051838.s55IcSJT014710>