回到 Slackware 和 RedHat-pre-Fedora 时代,有一种控制台字体有时被称为“rock”或“t”。我已经搜索过很多次了,但找不到任何参考资料。我认为如果可能的话,将其带回 Ubuntu 上会很有趣。有谁知道它现在叫什么,或者是否有 TrueType 版本我可以放在其他系统上?
答案1
据我所知,这种字体没有任何轮廓变体的现有端口。不过,这里有一些细节和技巧,可能会对您有所帮助。
这t.fnt,玻璃陨石,是由(前?)克莱斯米克软件,可能还有小拉尔夫·B·史密斯 (Ralph B Smith Jr),总裁/首席程序员/厨师/洗瓶工。它是一种位图字体,包含在 DOS 和 OS/2 的 VFONT 程序中。它加载 VGA 系统的替换字体。作者给出的名字是玻璃陨石并描述为“一种“建筑师”风格的字体。”
VFONT 可以下载的在档案 CVFONT.ZIP 和 CVFONTA.ZIP 中。这玻璃陨石字体是后者的一部分。前者是仅适用于 DOS 的旧版本。
VFONT和提取:
该档案由DOS程序VFONT.COM、OS/2程序VFONT2.EXE、字体数据库VFONT.DAT和README.MAN组成。 VFONT.DAT 包含 13 种连续存储的位图字体。要提取 Tektite 字体,请执行以下操作:
dd if=VFONT.DAT of=t.fnt bs=1 skip=28672 count=4096
这将为您提供 RAW 类型的字体文件,该文件包含在 Slackware 等中。
每个字体为 4096 字节。因此,要提取其他内容,只需更改跳过选项。即c.fnt
后面的t.fnt
给你一个跳跃值28672 + 4096 = 32768
。所有字体都包含在 Linux 中,要进行完整的提取,可以执行以下操作:
#!/bin/bash
pos=0
for n in s sd r ro rl mu ml t c b m mr sc; do
dd if=VFONT.DAT of=$n.fnt bs=1 skip=$pos count=4096
((pos += 4096))
done
...或者,当然,从包含它们的各种发行版之一下载它。
这些文件可以直接加载到终端中,例如:
setfont t.fnt
Linux 中的命名
该字体在 Linux 中由 VFONT 程序的选项命名。玻陨石有/T
。还包括其他字体,也由 VFONT 的命令行选项命名。 (/S = s.fnt,/SD = sd.fnt,/RO = ro.fnt... ETC。)
RAW 字体
(已过时但已被认可)RAW字体格式是最简单的字体格式。它没有页眉、页脚、转义字节等。它的宽度通常为 8 像素(位)——VFONT 字体也是如此。它们总是有 256 个字形。
由此我们可以很容易地计算出高度:
file_size (bits) 8 × 4096
h = -------------------- e.g. h = ------------- = 16
w × 256 8 × 256
由于所有 VFONT 字体的大小均为 4096,因此我们也知道它们的高度均为 16 像素(位)。这也使得每个字形为 16 个字节。
ASCII 渲染
由于字体符合 ASCII 范围(0x20(空格)- 0x7e(波形符)),因此我们可以对字形进行简单的 ASCII 渲染。
例如,字母的A
位置为 65。由于每个字形为 8×16 = 128 位,因此我们将它们设置为 128 / 8 = 16 字节。
由于 65 × 16 = 1040 我们可以通过以下方式提取字形A
(这里包括转换为二进制以及替换 0 和 1 以使其更具可读性):
xxd -s 1040 -l 16 -b -c 1 t.fnt | cut -d' ' -f 2 | tr 0 ' ' | tr 1 '#'
这给了我们:
Output from | Data in file
command: | Binary: Hex: Offset Offset
| Hex: Dec:
| 00000000 00 410 1040
| 00000000 00 411 1041
## | 00011000 18 412 1042
## | 00011000 18 413 1043
#### | 00111100 3c 414 1044
# # | 00100100 24 415 1045
## ## | 01100110 66 416 1046
## ### | 01101110 6e 417 1047
#### # | 01111010 7a 418 1048
### ## | 11100011 e3 419 1049
## ## | 11000011 c3 41a 1050
## ## | 11000011 c3 41b 1051
| 00000000 00 41c 1052
| 00000000 00 41d 1053
| 00000000 00 41e 1054
| 00000000 00 41f 1055
使用一些简单的 C 代码,我们还可以渲染一些简单的 PBM 图像。以下是 VFONT 中所有字体的示例输出:
使用 FontForge 进行编辑
如果您想使用该字体,我想您可能会去字体锻造。由于它无法识别 RAW 字体,您必须将其转换为其他格式。一种更简单的转换是 BDF。一种选择是使用约翰·埃利奥特 (John Elliot) 的 PSF 工具。首先从 RAW 转换为 PSF,然后将 PSF 转换为 BDF:
raw2psf t.fnt t.psf
psf2bdf t.psf t.bdf
BDF 文件现在可以在 FontForge 中打开
由于该过程相当简单(对于所有 VFONT 都相同),您还可以使用此脚本直接转换为 BDF 格式:
使用示例:
./raw2bdf Tektite t.fnt > t.bdf
为您提供 Tektite 字体作为 BDF。
#!/bin/bash
if [ $# -lt 2 ]; then
printf "Usage: %s <NAME> <raw-fnt-file>\n" $0
exit
fi
name=$1
file=$2
cat <<EOM
STARTFONT 2.1
FONT $name
SIZE 16 75 75
FONTBOUNDINGBOX 8 16 0 -4
STARTPROPERTIES 3
FONT_DESCENT 4
FONT_ASCENT 12
DEFAULT_CHAR 255
ENDPROPERTIES
CHARS 256
EOM
hexdump -ve '/1 "%02x\n"' "$file" | awk '
BEGIN {
n = 0;
}
(!((NR - 1) % 16)) {
if (n > 0)
print "ENDCHAR"
printf "STARTCHAR C00%02x\n"\
"ENCODING %d\n"\
"SWIDTH 666 0\n"\
"DWIDTH 8 0\n"\
"BBX 8 16 0 -4\n"\
"BITMAP\n",
n, n
++n
}
{
print $0
}
END {
print "ENDCHAR"
print "ENDFONT"
}
'
其他版本
Tektite 字体有多个修改版本。如果您搜索它,可以选择添加例如“神圣的”到您可以研究的搜索短语。
图像渲染
为了完整起见,我添加了混合的 C 代码来创建上面的图像。display
并且convert
是的一部分图像魔术师。
使用示例:
$ ./fntsampler t.fnt hello a
## ### ###
## ## ##
## ## ##
## ### ##### ## ## #####
## ## ## ## ## ## ## ## ##
#### #### ### ## ## ## ##
### ####### ## ## ## ##
## #### ## ## ## ##
## #### ## ## ## ## ##
## ## ###### ## ## #####
$ ./fntsampler t.fnt "Hello World!" > hello.pbm
$ display hello.pbm
上述所有字体的示例图像是由以下人员创建的:
$ for f in *.fnt; do ./fntsampler "$f" "$(printf "%-6s Hello ABC abc 123" "$f")" | convert - "${f%.*}.png"; done
$ convert -negate -append *.png collection.png
代码:
#include <stdio.h>
#include <errno.h>
#include <string.h>
int usage(char *me, char *s)
{
fprintf(stderr,
"Usage: %s <RAW-font-file> \"<string>\" [format] [[invert] | [dot] [blank]]\n\n"
" format p : PBM image (default).\n"
" a : ASCII.\n"
" invert i : invert b/w in PBM.\n"
" dot\n"
" blank : Dot / blank in ASCII mode.\n\n"
"%s\n"
,
me, errno ? "" : s
);
if (errno)
perror(s);
return 1;
}
int main(int argc, char *argv[])
{
char *me = argv[0];
char buf[4096];
size_t n;
char *p;
int i, j, k;
FILE *fh;
char *s;
char fmt = 'p', dot = '1', blank = '0';
if (argc < 3)
return usage(me, "Missing argument(s)");
if (!(fh = fopen(argv[1], "r")))
return usage(me, "Unable to open file");
if ((fread(buf, 1, 4096, fh) != 4096))
return usage(me, "Bad file size");
s = argv[2];
if ((n = strlen(s)) < 1)
return usage(me, "Empty string");
if (argc > 3)
fmt = argv[3][0];
if (fmt != 'a' && fmt != 'p')
return usage(me, "Unknown format");
if (fmt == 'a') {
dot = argc > 4 ? argv[4][0] : '#';
blank = argc > 5 ? argv[5][0] : ' ';
} else {
if (argc > 4 && argv[4][0] == 'i') {
dot = '0';
blank = '1';
}
printf("P1\n");
printf("#Text: \"%s\", using %s\n", s, argv[1]);
printf("%u 16\n", n * 8);
}
for (i = 0; i < 16; ++i) {
for (j = 0; j < (int)n; ++j) {
p = buf + (s[j] * 16) + i;
for (k = 7; k >= 0; --k) {
putchar((*p >> k) & 0x01 ? dot : blank);
}
/*putchar(' '); */
}
putchar('\n');
}
return 0;
}