# 字体与 FreeBSD

* 原文：[Fonts and FreeBSD](https://docs.freebsd.org/en/articles/fonts/)

## 摘要

本文档包含了与 FreeBSD 和 syscons 驱动程序、X11、Ghostscript 和 Groff 配合使用的各种字体文件的描述。提供了示例，展示如何将 syscons 显示模式切换到 80x60 模式，以及如何在上述应用程序中使用 Type 1 字体。

***

## 1. 引言

有许多字体来源可供选择，可能会有人问这些字体如何在 FreeBSD 上使用。答案可以通过仔细查阅文档来找到，特别是针对希望使用的组件。这是一个非常耗时的过程，因此本文尝试为其他感兴趣的人提供捷径。

## 2. 基本术语

有许多不同的字体格式和相关的字体文件后缀，下面列出了一些将要讨论的字体格式：

**.pfa**, **.pfb**\
PostScript® Type 1 字体。**.pfa** 是 *A*scii 格式，**.pfb** 是 *B*inary 格式。

.afm\
与 Type 1 字体相关的字体度量信息。

.pfm\
与 Type 1 字体相关的打印字体度量信息。

.ttf\
TrueType® 字体

.fot\
指向 TrueType 字体的间接引用（不是实际的字体）

.fon, **.fnt**\
位图屏幕字体

**.fot** 文件是 Windows® 用来作为指向实际 TrueType® 字体（**.ttf**）文件的符号链接。**.fon** 字体文件也由 Windows 使用。我不知道如何在 FreeBSD 上使用这种字体格式。

## 3. 我可以使用哪些字体格式？

哪种字体文件格式有用，取决于所使用的应用程序。FreeBSD 本身不使用任何字体。应用程序和/或驱动程序可能会使用字体文件。以下是应用程序/驱动程序与字体类型后缀的简要对照：

驱动程序 v&#x74;**.hex**

syscon&#x73;**.fnt**

应用程序 Ghostscrip&#x74;**.pfa**, **.pfb**, **.ttf**

X1&#x31;**.pfa**, **.pfb**

Grof&#x66;**.pfa**, **.afm**

Povra&#x79;**.ttf**

**.fnt** 后缀被广泛使用。我怀疑每当有人想为他们的应用程序创建一个特殊的字体文件时，他们往往会选择这个后缀。因此，很可能具有此后缀的文件并不全是相同的格式；特别是，FreeBSD 下 syscons 使用的 **.fnt** 文件可能与在 MS-DOS®/Windows® 环境中遇到的 **.fnt** 文件格式不同。我并没有尝试使用除 FreeBSD 提供的 **.fnt** 文件之外的其他 **.fnt** 文件。

## 4. 将虚拟控制台设置为 80x60 行模式

首先，必须加载一个 8x8 字体。为此，**/etc/rc.conf** 文件应包含以下行（根据你的语言环境更改字体名称）：

```sh
font8x8="iso-8x8"		# 从 /usr/share/syscons/fonts/* 中获取 8x8 字体（或者 NO）。
```

实际切换模式的命令是 [vidcontrol(1)](https://man.freebsd.org/cgi/man.cgi?query=vidcontrol\&sektion=1\&format=html)：

```sh
% vidcontrol VGA_80x60
```

各种基于屏幕的程序，如 [vi(1)](https://man.freebsd.org/cgi/man.cgi?query=vi\&sektion=1\&format=html)，必须能够确定当前的屏幕尺寸。由于这是通过 `ioctl` 调用到控制台驱动程序（如 [syscons(4)](https://man.freebsd.org/cgi/man.cgi?query=syscons\&sektion=4\&format=html)）来实现的，因此它们将正确地确定新的屏幕尺寸。

为了使这一过程更加顺畅，可以将这些命令嵌入到启动脚本中，以便系统启动时自动执行。为此，可以在 **/etc/rc.conf** 中添加以下行：

```sh
allscreens_flags="VGA_80x60"	# 为所有虚拟屏幕设置此 vidcontrol 模式
```

参考资料：[rc.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=rc.conf\&sektion=5\&format=html)，[vidcontrol(1)](https://man.freebsd.org/cgi/man.cgi?query=vidcontrol\&sektion=1\&format=html)。

## 5. 在 X11 中使用 Type 1 字体

X11 可以使用 **.pfa** 或 **.pfb** 格式的字体。X11 字体位于 **/usr/X11R6/lib/X11/fonts** 目录下的多个子目录中。每个字体文件都通过各个目录中的 **fonts.dir** 文件与其 X11 名称进行交叉引用。

已经有一个名为 **Type1** 的目录。最直接的添加新字体的方式是将其放入此目录。更好的方法是将所有新字体保存在单独的目录中，并使用符号链接来引用额外的字体。这样可以更轻松地跟踪自己的字体，而不会与最初提供的字体混淆。例如：

```sh
创建一个目录来存放字体文件
% mkdir -p /usr/local/share/fonts/type1
% cd /usr/local/share/fonts/type1

将 .pfa、.pfb 和 .afm 文件放在这里

也可以想要在这里保留 readme 文件和其他文档

% cp /cdrom/fonts/atm/showboat/showboat.pfb .
% cp /cdrom/fonts/atm/showboat/showboat.afm .

维护一个索引以交叉引用字体
% echo showboat - InfoMagic CICA, Dec 1994, /fonts/atm/showboat >>INDEX
```

现在，要在 X11 中使用新字体，必须使字体文件可用并更新字体名称文件。X11 字体名称看起来像这样：

```sh
-bitstream-charter-medium-r-normal-xxx-0-0-0-0-p-0-iso8859-1
     |        |      |    |   |     |  | | | | | |    \    \
     |        |      |    |   |     \  \ \ \ \ \ \     +----+- 字符集
     |        |      |    |   \      \  \ \ \ \ \ +- 平均宽度
     |        |      |    |    \      \  \ \ \ \ +- 间距
     |        |      |    \	\      \  \ \ \ \ +- 垂直分辨率
     |        |      |     \	 \	\  \ \ \ +- 水平分辨率
     |        |      |      \	  \	 \  \ +- 点数
     |        |      |       \     \	  \  +- 像素
     |        |      |        \     \	   \
  字体厂商  字体家族  粗细   倾斜  宽度  额外风格
```

每个新字体都需要创建一个新的名称。如果你有字体文档中附带的信息，可以将其作为创建名称的基础。如果没有相关信息，可以通过使用 [strings(1)](https://man.freebsd.org/cgi/man.cgi?query=strings\&sektion=1\&format=html) 命令查看字体文件来获取一些线索。例如：

```sh
% strings showboat.pfb | more
%!FontType1-1.0: Showboat 001.001
%%CreationDate: 1/15/91 5:16:03 PM
%%VMusage: 1024 45747
% Generated by Fontographer 3.1
% Showboat
 1991 by David Rakowski.  Alle Rechte Vorbehalten.
FontDirectory/Showboat known{/Showboat findfont dup/UniqueID known{dup
/UniqueID get 4962377 eq exch/FontType get 1 eq and}{pop false}ifelse
{save true}{false}ifelse}{false}ifelse
12 dict begin
/FontInfo 9 dict dup begin
 /version (001.001) readonly def
 /FullName (Showboat) readonly def
 /FamilyName (Showboat) readonly def
 /Weight (Medium) readonly def
 /ItalicAngle 0 def
 /isFixedPitch false def
 /UnderlinePosition -106 def
 /UnderlineThickness 16 def
 /Notice (Showboat
 1991 by David Rakowski.  Alle Rechte Vorbehalten.) readonly def
end readonly def
/FontName /Showboat def
--stdin--
```

使用这些信息，一个可能的字体名称是：

```sh
-type1-Showboat-medium-r-normal-decorative-0-0-0-0-p-0-iso8859-1
```

我们名称的组成部分如下：

**Foundry（字体厂商）**\
我们将所有新字体命名为 `type1`。

**Family（字体家族）**\
字体的名称。

**Weight（粗细）**\
如正常、粗体、中等、半粗体等。从上面使用 [strings(1)](https://man.freebsd.org/cgi/man.cgi?query=strings\&sektion=1\&format=html) 命令输出来看，这个字体的粗细是 *medium*。

**Slant（倾斜）***roman*、*italic*、*oblique* 等。由于 *ItalicAngle* 为零，使用 *roman*。

**Width（宽度）**\
正常、宽、紧凑、扩展等。假设为 *normal*，直到字体能被检查为止。

**Additional style（额外风格）**\
通常被省略，但这将指示字体包含装饰性的大写字母。

**Spacing（间距）**\
比例间距或等宽。由于 *isFixedPitch* 为 false，使用 *proportional*。

所有这些名称都是任意的，但应尽量与现有的命名约定兼容。字体是通过名称和可能的通配符由 X11 程序引用的，因此所选名称应具有一定的合理性。可以从简单地使用

```sh
...-normal-r-normal-...-p-...
```

作为名称开始，然后使用 [xfontsel(1)](https://man.freebsd.org/cgi/man.cgi?query=xfontsel\&sektion=1\&format=html) 查看字体并根据字体的外观调整名称。

因此，完成我们的示例：

```sh
使字体对 X11 可访问
% cd /usr/X11R6/lib/X11/fonts/Type1
% ln -s /usr/local/share/fonts/type1/showboat.pfb .

编辑 fonts.dir 和 fonts.scale，添加描述字体的行，并在第一行中递增字体的数量。
% ex fonts.dir
:1p
25
:1c
26
.
:$a
showboat.pfb -type1-showboat-medium-r-normal-decorative-0-0-0-0-p-0-iso8859-1
.
:wq

fonts.scale 看起来与 fonts.dir 相同...
% cp fonts.dir fonts.scale

告诉 X11 发生了变化
% xset fp rehash

检查新字体
% xfontsel -pattern -type1-*
```

参考资料：[xfontsel(1)](https://man.freebsd.org/cgi/man.cgi?query=xfontsel\&sektion=1\&format=html)，[xset(1)](https://man.freebsd.org/cgi/man.cgi?query=xset\&sektion=1\&format=html)，《The X Windows System in a Nutshell》，[O’Reilly & Associates](http://www.ora.com/)。

## 6. 使用 Type 1 字体与 Ghostscript

Ghostscript 通过其 **Fontmap** 引用字体。这个文件必须以类似于 X11 **fonts.dir** 的方式进行修改。Ghostscript 可以使用 **.pfa** 或 **.pfb** 格式的字体。使用之前示例中的字体，以下是如何将其与 Ghostscript 一起使用：

```sh
将字体放入 Ghostscript 的字体目录
% cd /usr/local/share/ghostscript/fonts
% ln -s /usr/local/share/fonts/type1/showboat.pfb .

编辑 Fontmap 以便 Ghostscript 知道字体
% cd /usr/local/share/ghostscript/4.01
% ex Fontmap
:$a
/Showboat        (showboat.pfb) ; % 来自 CICA /fonts/atm/showboat
.
:wq

使用 Ghostscript 检查字体
% gs prfont.ps
Aladdin Ghostscript 4.01 (1996-7-10)
Copyright (C) 1996 Aladdin Enterprises, Menlo Park, CA.  All rights
reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
从 /usr/local/share/ghostscript/fonts/tir_____.pfb 加载 Times-Roman 字体...
 /1899520 581354 1300084 13826 0 完成。
GS>Showboat DoFont
从 /usr/local/share/ghostscript/fonts/showboat.pfb 加载 Showboat 字体...
 1939688 565415 1300084 16901 0 完成。
>>showpage, 按 <return> 键继续<<
>>showpage, 按 <return> 键继续<<
>>showpage, 按 <return> 键继续<<
GS>quit
```

参考资料：Ghostscript 4.01 分发包中的 **fonts.txt**

## 7. 使用 Type 1 字体与 Groff

现在，我们可以在 X11 和 Ghostscript 中使用新字体，那么如何在 Groff 中使用这个新字体呢？首先，由于我们使用的是 Type 1 PostScript® 字体，适用于 Groff 的设备是 *ps* 设备。必须为每个字体创建一个 Groff 字体文件。Groff 字体名实际上就是 **/usr/share/groff\_font/devps** 目录中的一个文件。对于我们的示例，字体文件可以是 **/usr/share/groff\_font/devps/SHOWBOAT**。该文件必须使用 Groff 提供的工具创建。

第一个工具是 `afmtodit`。这个工具通常没有安装，因此必须从源代码分发版中获取。我发现需要修改文件的第一行，所以我做了如下操作：

```sh
% cp /usr/src/gnu/usr.bin/groff/afmtodit/afmtodit.pl /tmp
% ex /tmp/afmtodit.pl
:1c
#!/usr/bin/perl -P-
.
:wq
```

这个工具将根据字体度量文件（**.afm** 后缀）创建 Groff 字体文件。继续我们的示例：

```sh
许多 .afm 文件是 Mac 格式的，行由 ^M 分隔
我们需要将它们转换为 UNIX(R) 风格的 ^J 分隔行
% cd /tmp
% cat /usr/local/share/fonts/type1/showboat.afm |
	tr '\015' '\012' >showboat.afm

现在创建 Groff 字体文件
% cd /usr/share/groff_font/devps
% /tmp/afmtodit.pl -d DESC -e text.enc /tmp/showboat.afm generate/textmap SHOWBOAT
```

现在，字体可以通过名称 SHOWBOAT 引用。

如果系统使用 Ghostscript 驱动打印机，那么不需要做更多的操作。然而，如果使用真正的 PostScript® 打印机，则必须将字体下载到打印机中才能使用该字体（除非打印机内建 Showboat 字体或字体磁盘可访问）。最后一步是创建一个可下载的字体。使用 `pfbtops` 工具创建 **.pfa** 格式的字体，并修改 **download** 文件以引用新字体。**download** 文件必须引用字体的内部名称。可以通过查看 Groff 字体文件轻松确定这个名称，如下所示：

```sh
创建 .pfa 字体文件
% pfbtops /usr/local/share/fonts/type1/showboat.pfb >showboat.pfa
```

当然，如果 **.pfa** 已经存在，只需使用符号链接引用它。

```sh
获取内部字体名称
% fgrep internalname SHOWBOAT
internalname Showboat
告诉 Groff 字体需要被下载
% ex download
:$a
Showboat      showboat.pfa
.
:wq
```

测试字体：

```sh
% cd /tmp
% cat >example.t <<EOF
.sp 5
.ps 16
这是 Showboat 字体的示例：
.br
.ps 48
.vs (\n(.s+2)p
.sp
.ft SHOWBOAT
ABCDEFGHI
.br
JKLMNOPQR
.br
STUVWXYZ
.sp
.ps 16
.vs (\n(.s+2)p
.fp 5 SHOWBOAT
.ft R
要使用它作为段落的第一个字母，它会显示如下：
.sp 50p
\s(48\f5H\s0\fRere 是段落的第一个字母，使用 Showboat 字体。
需要额外的垂直空间来为较大的字母留出空间。
EOF
% groff -Tps example.t >example.ps

使用 Ghostscript/Ghostview
% ghostview example.ps

打印
% lpr -Ppostscript example.ps
```

参考资料：**/usr/src/gnu/usr.bin/groff/afmtodit/afmtodit.man**， [groff\_font(5)](https://man.freebsd.org/cgi/man.cgi?query=groff_font\&sektion=5\&format=html)， [groff\_char(7)](https://man.freebsd.org/cgi/man.cgi?query=groff_char\&sektion=7\&format=html)， [pfbtops(1)](https://man.freebsd.org/cgi/man.cgi?query=pfbtops\&sektion=1\&format=html).

## 8. 将 TrueType 字体转换为适用于 Groff/PostScript 格式的字体

这可能需要一些工作，因为它依赖于一些并没有作为基础系统一部分安装的工具。它们包括：

`ttf2pf`：TrueType 到 PostScript 转换工具。它允许将 TrueType 字体转换为 ASCII 字体度量文件（**.afm**）。

目前可通过 <http://sunsite.icm.edu.pl/pub/GUST/contrib/BachoTeX98/ttf2pf/> 下载。注意：这些文件是 PostScript 程序，必须通过按住 Shift 键并点击链接来下载，否则浏览器可能会尝试启动 Ghostview 来查看它们。

感兴趣的文件包括：

* **GS\_TTF.PS**
* **PF2AFM.PS**
* **ttf2pf.ps**\
  这些文件的奇怪大小写是因为它们也旨在支持 DOS shell。因此，任何重命名必须与此一致。（实际上，**GS\_TTF.PS** 和 **PFS2AFM.PS** 应该是 Ghostscript 分发版的一部分，但使用这些作为独立工具同样有效。FreeBSD 似乎没有包含后者。）你也可能希望将它们安装到 **/usr/local/share/groff\_font/devps**（？）目录下。

`afmtodit`：从 ASCII 字体度量文件创建 Groff 字体文件。通常该工具位于目录 **/usr/src/contrib/groff/afmtodit** 中，且需要一些工作才能启动。

> **注意**
>
> 如果你不想在 **/usr/src** 目录下工作，只需将上述目录的内容复制到工作位置即可。

在工作目录中，需要构建该工具。只需输入以下命令：

```sh
# make -f Makefile.sub afmtodit
```

你可能还需要将 **/usr/contrib/groff/devps/generate/textmap** 复制到 **/usr/share/groff\_font/devps/generate**，如果该文件尚不存在。

这些工具准备好后，你就可以开始操作：

1. 创建 **.afm** 文件，输入以下命令：

   ```sh
   % gs -dNODISPLAY -q -- ttf2pf.ps TTF_name PS_font_name AFM_name
   ```

   其中，*TTF\_name* 是你的 TrueType 字体文件，*PS\_font\_name* 是 **.pfa** 的文件名，*AFM\_name* 是你希望为 **.afm** 文件指定的名称。如果你没有为 **.pfa** 或 **.afm** 文件指定输出文件名，那么将使用 TrueType 字体文件名生成默认名称。

   这也会生成一个 **.pfa** 文件，即 ASCII PostScript 字体度量文件（**.pfb** 是二进制形式）。虽然这个文件不一定需要，但它（我认为）对于字体服务器可能会有用。

   例如，若要将 30f9 Barcode 字体转换为默认文件名，可以使用以下命令：

   ```sh
   % gs -dNODISPLAY -- ttf2pf.ps 3of9.ttf
   Aladdin Ghostscript 5.10 (1997-11-23)
   Copyright (C) 1997 Aladdin Enterprises, Menlo Park, CA.  All rights reserved.
   This software comes with NO WARRANTY: see the file PUBLIC for details.
   Converting 3of9.ttf to 3of9.pfa and 3of9.afm.
   ```

   如果你希望将转换后的字体存储为 **A.pfa** 和 **B.afm**，可以使用以下命令：

   ```sh
   % gs -dNODISPLAY -- ttf2pf.ps 3of9.ttf A B
   Aladdin Ghostscript 5.10 (1997-11-23)
   Copyright (C) 1997 Aladdin Enterprises, Menlo Park, CA.  All rights reserved.
   This software comes with NO WARRANTY: see the file PUBLIC for details.
   Converting 3of9.ttf to A.pfa and B.afm.
   ```
2. 创建 Groff PostScript 文件：\
   切换到 **/usr/share/groff\_font/devps** 目录以便执行以下命令。你可能需要 root 权限来执行这些命令。（如果你不想在该目录中工作，确保引用 **DESC**、**text.enc** 和 **generate/textmap** 文件，并在此目录中找到它们。）

   ```sh
   % afmtodit -d DESC -e text.enc file.afm generate/textmap PS_font_name
   ```

   其中，**file.afm** 是上面使用 `ttf2pf.ps` 创建的 *AFM\_name* 文件，*PS\_font\_name* 是该命令使用的字体名称，也是 [groff(1)](https://man.freebsd.org/cgi/man.cgi?query=groff\&sektion=1\&format=html) 用于引用此字体的名称。例如，假设你使用了第一个 `ttf2pf.ps`，那么可以使用以下命令创建 3of9 Barcode 字体：

   ```sh
   % afmtodit -d DESC -e text.enc 3of9.afm generate/textmap 3of9
   ```

   确保将生成的 *PS\_font\_name* 文件（例如上述示例中的 **3of9**）放置在 **/usr/share/groff\_font/devps** 目录中，可以通过复制或移动来完成。

   注意，如果 **ttf2pf.ps** 使用 TrueType 字体文件中的字体名称来指定字体名称，并且你希望使用不同的名称，必须在运行 `afmtodit` 之前编辑 **.afm** 文件。此名称还必须与 Fontmap 文件中的名称匹配，如果你希望将 [groff(1)](https://man.freebsd.org/cgi/man.cgi?query=groff\&sektion=1\&format=html) 输入管道传递给 [gs(1)](https://man.freebsd.org/cgi/man.cgi?query=gs\&sektion=1\&format=html)。

## 9. TrueType 字体能否与其他程序一起使用？

TrueType 字体格式被 Windows、Windows 95 和 Mac 操作系统使用，十分流行，目前有大量的字体可供选择。

遗憾的是，目前我所知道的能够使用这种格式的应用程序不多：Ghostscript 和 Povray 就是其中之一。根据文档，Ghostscript 对 TrueType 字体的支持比较初步，效果可能不如 Type 1 字体。Povray 版本 3 也能使用 TrueType 字体，但我怀疑很少有人会创建一系列的光线追踪页面来生成文档 :-)。

这种情况可能很快会有所改变。[FreeType 项目](http://www.freetype.org/) 正在开发一套有用的 FreeType 工具：

* `xfsft` 字体服务器可为 X11 提供 TrueType 字体服务，除了常规字体外。虽然目前仍处于测试阶段，但据说它非常实用。更多信息请见 [Juliusz Chroboczek 的页面](http://www.dcs.ed.ac.uk/home/jec/programs/xfsft/)。FreeBSD 的移植说明可以在 [Stephen Montgomery 的软件页面](http://math.missouri.edu/~stephen/software/) 找到。
* xfstt 是另一个 X11 字体服务器，可以在 <ftp://sunsite.unc.edu/pub/Linux/X11/fonts/> 获取。
* 一个名为 `ttf2bdf` 的程序可以从 TrueType 字体文件生成适合 X 环境使用的 BDF 文件。据说 Linux 的二进制文件可以从 <ftp://crl.nmsu.edu/CLR/multiling/General/> 获取。
* 以及其他工具...

## 10. 从哪里可以获得其他的字体？

许多字体可以在互联网上找到。这些字体要么是完全免费的，要么是共享软件。此外，许多字体也可以在 Ports 中的 **x11-fonts/** 目录中找到。

## 11. 其他问题

* **.pfm** 文件有什么用途？
* 是否可以从 **.pfa** 或 **.pfb** 文件生成 **.afm** 文件？
* 如何为具有非标准字符名称的 PostScript 字体生成 groff 字符映射文件？
* 是否可以设置 xditview 和 devX?? 设备来访问所有新的字体？
* 为 Povray 和 Ghostscript 提供使用 TrueType 字体的示例会很有用。
