2个版本
0.1.1 | 2024年2月2日 |
---|---|
0.1.0 | 2024年1月28日 |
#973 in 编码
125KB
1.5K SLoC
一个用于处理TeX字体中码点的crate。
lib.rs
:
这个crate提供了一种访问TeX字体中字符的方法。它旨在由使用tex_engine
的crate使用。
TeX通过解析字体度量文件(.tfm
文件)来处理字体,这些文件包含字体中每个字符尺寸的信息。因此,从TeX(核心)的角度来看,一个字符只是一个指向字体度量文件的索引 $0 \leq i \leq 255$。
为了找出字符实际的外观,我们理想情况下想了解相应的Unicode码点。这个crate试图做到这一点。
用法
这个crate试图将一个tex字体(通过其.tfm
文件的文件名基础标识)与
- 一系列
FontModifier
(例如粗体、斜体、无衬线等)相关联 - 一个
GlyphList
,即一个长度为256的数组[
Glyph
;256]
一个Glyph
要么是未定义的(即该字符不在字体中,或者crate无法确定其确切内容)或者可以呈现为一个字符串。
例如,考虑\mathbf{\mathit{\Gamma^\kappa_\ell}}
(即 $\mathbf{\mathit{\Gamma^\kappa_\ell}}$)。从TeX的角度来看,这是一个由3个字符组成的序列,表示为字体 cmmib10
的索引,即0、20和96。
下面是如何使用这个crate来获取相应的Unicode字符,即𝜞
、𝜿
和ℓ
的示例。
实例化
首先,我们使用一个函数来实例化一个 FontInfoStore
,该函数允许它找到文件。这个函数应该接受一个字符串(例如 cmmib10.tfm
)并返回一个字符串(例如 /usr/share/texmf-dist/fonts/tfm/public/cm/cmmib10.tfm
)。例如,可以通过调用 kpsewhich
来完成,但重复和频繁地调用 kpsewhich
很慢,所以建议使用更高效的替代方案。
use tex_glyphs::encodings::FontInfoStore;
let mut store = FontInfoStore::new(|s| {
std::str::from_utf8(std::process::Command::new("kpsewhich")
.args(vec!(s)).output().expect("kpsewhich not found!")
.stdout.as_slice()).unwrap().trim().to_string()
});
这个存储现在将使用提供的函数来查找您的 pdftex.map
文件,该文件列出了 TeX 可用的所有字体,并将它们与 .enc
、.pfa
和 .pfb
文件相关联。
获取字形
如果我们现在查询存储以获取某些字体(例如 cmmib10
)的 GlyphList
,如下所示
let ls = store.get_glyphlist("cmmib10");
...它将尝试解析与 cmmib10
相关的 .enc
文件,如果存在的话。如果没有,或者解析失败,它将尝试解析 .pfa
或 .pfb
文件。如果这两个都不起作用,它将搜索 .vf
文件并尝试解析它。如果这也失败了,它将返回一个空的 GlyphList
。
从这三个来源中的任何一个,它都会尝试将每个字节索引与一个 Glyph
相关联
let zero = ls.get(0);
let twenty = ls.get(20);
let ninety_six = ls.get(96);
println!("0={}={}, 20={}={}, and 96={}={}",
zero.name(),zero,
twenty.name(),twenty,
ninety_six.name(),ninety_six
);
0=Gamma=Γ, 20=kappa=κ, and 96=lscript=ℓ
字体修饰符
到目前为止,一切顺利 - 但字形不是粗体或斜体,而是在 cmmib10
中它们是。所以让我们来看看 cmmib10
有什么属性
let font_info = store.get_info("cmmib10").unwrap();
println!("{:?}",font_info.styles);
println!("{:?}",font_info.weblink);
ModifierSeq { blackboard: false, fraktur: false, script: false, bold: true, capitals: false, monospaced: false, italic: true, oblique: false, sans_serif: false }
Some(("Latin Modern Math", "https://fonts.cdnfonts.com/css/latin-modern-math"))
...这告诉我们该字体是粗体和斜体的,但不是无衬线,等宽等。它还告诉我们,该字体的公开可用的网络兼容等价字体称为 "Latin Modern Math",并且如果我们想在例如 HTML 中使用它,我们可以通过提供的 URL 找到它 :)
现在我们只需要将修饰符应用到字形上
use tex_glyphs::fontstyles::FontModifiable;
println!("{}, {}, and {}",
zero.to_string().apply(font_info.styles),
twenty.to_string().apply(font_info.styles),
ninety_six.to_string().apply(font_info.styles)
);
𝜞, 𝜿, and ℓ
apply
方法来自 trait FontModifiable
,该 trait 为任何实现了 AsRef<str>
的类型实现,包括 &str
和 String
。它还提供了更直接的方法,例如 make_bold
、make_italic
、make_sans
等。
修正错误
上述确定字形和字体修饰符的程序绝对不是完美的;不仅因为 enc
和 pfa/
pfb
文件可能包含错误或不为人知的字形名称,而且还因为字体修饰符是通过启发式方法确定的。因此,我们提供了一种修正错误的方法
- 字形名称到 Unicode 的映射存储在文件 glyphmap.txt 中
- 字体修饰符、网络字体名称和链接,甚至完整的字形列表都可以添加到 markdown 文件 patches.md 中,该文件还作为修复任何可能发现的错误的指南。
这两个文件在编译过程中都会被解析。
如果您注意到任何错误,请随时为这些文件打开一个 pull request。
依赖项
~1.3–2MB
~36K SLoC