Skip to content

怎么把 cal 字体变成 LaTeX 里 mathcal 默认的那种?

怎么把 cal 字体变成 LaTeX 里 mathcal 默认的那种?

Typst 中数学字体默认是 New Computer Modern Math,与 LaTeX 中默认[1]的 Computer Modern Math 略有不同。

若想使用 LaTeX 默认的\mathcal花体,请按以下两种方法之一更换字体。

另外,LaTeX 中有 calligraphic 和 script 两种花体,此处是前者;后者请参考如何实现\mathscr的花体符号

法一:使用修改版字体(推荐)

  1. 下载CMSY10-fix_cmap_kerning.otf并安装
  2. 如下设置covers
typst
修改前 $cal(K M Z), cal(P)_n, cal(T)^p$

#show math.equation: set text(font: (
  (name: "Computer Modern Symbol", covers: regex("[𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩-𝒬ℛ𝒮-𝒵]")),
  "New Computer Modern Math",
))
修改后 $cal(K M Z), cal(P)_n, cal(T)^p$
Typst compiled image

该字体的字形与法二相同,但将字符重新映射到了正确的 Unicode 码位,并补充了 MathKernInfo、MathItalicsCorrectionInfo 等信息。感谢网友“请输入密码”进行修改工作并无偿分享。

为何正则表达式如此凌乱?

以上正则表达式[𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩-𝒬ℛ𝒮-𝒵]不可简省为[𝒜-𝒵]。由于历史原因,大写花体字母的编码并不连续,而分散在 Letterlike Symbols 和 Mathematical Alphanumeric Symbols 两块。具体可参考 typst/codex 源代码Mathematical Alphanumeric Symbols - Wikipedia

需要同时使用 scr?

以上设置会同时影响cal(A)scr(A),因为 Unicode 把它们统一编码了[2]

如需同时使用二者,请自定义函数设置字体。

typst
默认字体效果 $cal(L)^p != scr(L)^p, cal(a)_n = scr(a)_n$

#show math.equation: set text(font: (
  (name: "Computer Modern Symbol", covers: regex("[𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩-𝒬ℛ𝒮-𝒵]")),
  "New Computer Modern Math",
))
更换字体之后 $cal(L)^p = scr(L)^p, cal(a)_n = scr(a)_n$

#let scr(it) = text( 
  font: "New Computer Modern Math", 
  $std.math.scr(it)$, 
) 
自定义`scr`后 $cal(L)^p != scr(L)^p, cal(a)_n = scr(a)_n$
Typst compiled image
typst
#let cal(it) = text(
  font: ("Computer Modern Symbol", "New Computer Modern Math"),
  $std.math.scr(it)$,
)
只自定义`cal`也可行 $cal(L)^p != scr(L)^p, cal(a)_n = scr(a)_n$
Typst compiled image

法二:使用原版字体

  1. 从 matplotlib 的mpl-data/fonts/ttf/文件夹下载cmsy10.ttf并安装
  2. 如下设置font: "cmsy10"并用upright切换到普通码位
typst
#let cal(s) = text(font: "cmsy10", math.upright(s))
$ cal(K M Z) != std.math.cal(K M Z) $
Typst compiled image
为何出现 matplotlib?

Computer Modern Math 早于 OpenType 技术标准,通常以 Type 1 字体形式存在,如cmsy10.pfm

今天很多软件都不支持*.pfm。matplotlib 开发者将它转换成了cmsy10.ttf,可供 Typst 等软件使用。

该方法存在以下若干问题,主要为介绍原理而保留;法一通过修改字体解决了这些问题,实用时还是推荐法一。

上下标位置不对

cmsy10.ttf缺少 MathKernInfo 等信息,导致上下标位置异常。其中,竖直位置有玄学办法勉强修补(加上context),而水平位置则无已知办法能完全解决。

typst
#set align(end)

正常效果 $cal(P)_n, cal(T)^p$

#let cal(s) = text(font: "cmsy10", math.upright(s))
异常效果 $cal(P)_n, cal(T)^p$

#let cal(s) = context text(font: "cmsy10", math.upright(s))
勉强修补后 $cal(P)_n, cal(T)^p$
Typst compiled image

更全面的测试请参考 How to use (old) Computer Modern for math.cal? And why context matters? - Questions - Typst Forum

码位不是数学字符

该方法中,大写字母复制出来是KMZ(ASCII)而非𝒦︀ℳ︀𝒵(Unicode 数学字符),而其余字符更是连显示也不对。这是因为原版cmsy10.ttf设置的码位不符合今日习惯,如对比表格所示。

对比表格
typst
#let examples = (
  [ABC],
  $cal(A B C)$,
  [abc],
  [012],
  $cal(T) x - 2 y >> cal(A)$,
  "!#%()",
  $-> => arrow.r.quad arrow.tr arrow.b$,
  "~£¥§μ¶",
  [ÀÁÂÃÄÅ],
)

#set table(stroke: none, align: center + horizon)
#table(
  columns: 3,
  table.header[*New Computer \ Modern*][*原版\ CMSY10*][*修改版\ CMSY10*],
  table.hline(), table.vline(x: 1), table.vline(x: 2),
  ..examples
    .map(it => ("New Computer Modern Math", "cmsy10", "Computer Modern Symbol").map(font => {
      set text(font: font, fallback: false)
      show math.equation: set text(font: font)
      it
    }))
    .flatten(),
)
Typst compiled image
log
warning: current font is not designed for math
  ┌─ <stdin>:6:2

6 │   $cal(A B C)$,
  │   ^^^^^^^^^^^^

  = hint: rendering may be poor

warning: current font is not designed for math
  ┌─ <stdin>:9:2

9 │   $cal(T) x - 2 y >> cal(A)$,
  │   ^^^^^^^^^^^^^^^^^^^^^^^^^^

  = hint: rendering may be poor

warning: current font is not designed for math
   ┌─ <stdin>:11:2

11 │   $-> => arrow.r.quad arrow.tr arrow.b$,
   │   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

   = hint: rendering may be poor

TIP

上例出现警告是正常现象。


  1. 此处指不使用 unicode-math 时的默认数学字体;若使用 unicode-math,默认字体是 New Computer Modern Math,Typst 效果与之相同。 ↩︎

  2. 其实还标准化了用于区分的变体序列。不过目前 typst、正则表达式、字体的支持都很有限,它对我们设置字体没有什么帮助。 ↩︎

What do you think?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v3.5.1

基于 MIT 许可发布