LaTex 中圓圈序號及一些特殊字元的輸入
眾所周知,LATEX 提供了 \textcircled
命令用以給字元加圈,但效果卻不怎麼好:
實際上,加圈並不是一個平凡的變換,它會涉及到圈內字元形狀的微調,而這是幾乎無法在 TEX 宏層面解決的。因此,要得到比較好的效果,最好能使用預先設計的字元形(glyph)。
傳統方案
pifont
宏包提供了一系列雜錦符號(dingbats),其中就有帶圈數字。pifont
屬於 psnfss
宏集,它封裝了一系列 PostScript 字體,包含著名的 Helvetica、Times、Courier 等。pifont
使用的是 Zapf Dingbats 字體。
使用 \ding{<number>}
可以很方便地使用帶圈數字(共有四種),當然也有其他符號。具體數字可參見下圖:
在主流的 TEX 引擎下,pifont
宏包都可以使用。
Unicode
數字 0–50 的帶圈版本都分配了對應的 Unicode 碼位,因而在現代 TEX 引擎(XETEX 和 LuaTEX,若無特殊說明以下僅討論這兩者)中,配合合適的字體,理論上可以直接輸入這些符號。具體見下表:[1]
⓪ | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
---|---|---|---|---|---|---|---|---|---|---|
24EA | 2460 | 2461 | 2462 | 2463 | 2464 | 2465 | 2466 | 2467 | 2468 | 2469 |
⑪ | ⑫ | ⑬ | ⑭ | ⑮ | ⑯ | ⑰ | ⑱ | ⑲ | ⑳ | |
246A | 246B | 246C | 246D | 246E | 246F | 2470 | 2471 | 2472 | 2473 | |
㉑ | ㉒ | ㉓ | ㉔ | ㉕ | ㉖ | ㉗ | ㉘ | ㉙ | ㉚ | |
3251 | 3252 | 3253 | 3254 | 3255 | 3256 | 3257 | 3258 | 3259 | 325A | |
㉛ | ㉜ | ㉝ | ㉞ | ㉟ | ㊱ | ㊲ | ㊳ | ㊴ | ㊵ | |
325B | 325C | 325D | 325E | 325F | 32B1 | 32B2 | 32B3 | 32B4 | 32B5 | |
㊶ | ㊷ | ㊸ | ㊹ | ㊺ | ㊻ | ㊼ | ㊽ | ㊾ | ㊿ | |
32B6 | 32B7 | 32B8 | 32B9 | 32BA | 32BB | 32BC | 32BD | 32BE | 32BF |
Zapf Dingbats 中的其他幾種樣式也分配有碼位:
-
反白(negative circled digits)
⓿ ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿ 24FF 2776 2777 2778 2779 277A 277B 277C 277D 277E 277F ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ 24EB 24EC 24ED 24EE 24EF 24F0 24F1 24F2 24F3 24F4 -
無襯線(circled sans-serif digits)
🄋 ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ 1F10B 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 -
無襯線反白(negative circled sans-serif digits)
🄌 ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓ 1F10C 278A 278B 278C 278D 278E 278F 2790 2791 2792 2793
此外,還額外增加了一些樣式:
-
雙線(double circled digits)
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ 24F5 24F6 24F7 24F8 24F9 24FA 24FB 24FC 24FD 24FE -
加框(circled numbers on black square)
㉈ ㉉ ㉊ ㉋ ㉌ ㉍ ㉎ ㉏ 3248 3249 324A 324B 324C 324D 324E 324F -
帶圓括弧(parenthesized digits)
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ 2474 2475 2476 2477 2478 2479 247A 247B 247C 247D ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ 247E 247F 2480 2481 2482 2483 2484 2485 2486 2487 -
帶點(digits with full stop)
🄀 ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ 1F100 2488 2489 248A 248B 248C 248D 248E 248F 2490 2491 ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ 2492 2493 2494 2495 2496 2497 2498 2499 249A 249B -
帶逗號(digits with comma)
🄁 🄂 🄃 🄄 🄅 🄆 🄇 🄈 🄉 🄊 1F101 1F102 1F103 1F104 1F105 1F106 1F107 1F108 1F109 1F10A -
這些姑且也算上吧:
㈠ ㈡ ㈢ ㈣ ㈤ ㈥ ㈦ ㈧ ㈨ ㈩ 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 ㊀ ㊁ ㊂ ㊃ ㊄ ㊅ ㊆ ㊇ ㊈ ㊉ 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 🈩 🈔 🈪 1F229 1F214 1F22A 🉂 🉁 1F242 1F241
這些符號分散在以下幾個 Unicode 區塊(block)中:
- Enclosed Alphanumerics (U+2460–U+24FF)
- 帶圈 0–20(以及 a–z、A–Z)
- 反白 0、11–20
- 雙線 1–10
- 帶圓括弧 1–20
- 帶點 1–20
- Dingbats (U+2700–U+27BF)
- 反白 1–10
- 無襯線 1–10
- 無襯線反白 1–10
- Enclosed CJK Letters and Months (U+3200–U+32FF)
- 帶圈 21–50
- 加框 10–80(僅限整十)
- 帶圈
一
~十
- 帶圓括弧
一
~十
- Enclosed Alphanumeric Supplement (U+1F100–U+1F1FF)
- 帶逗號 0–9
- 無襯線、無襯線反白以及帶點的 0
- Enclosed Ideographic Supplement (U+1F200–U+1F2FF)
- 帶方框
一
、二
、三
- 帶六角括弧
二
、三
- 帶方框
直接輸入,或者利用碼位,都能在 LATEX 中使用以上這些帶圈數字(注意不同方法對大小寫的要求有差異):
\documentclass{article}
\usepackage{fontspec}
\setmainfont{Source Han Serif SC}
\begin{document}
① ② ③ ④ ⑤
\symbol{"2776} \symbol{"2777} \symbol{"2778} \symbol{"2779} \symbol{"277A}
\char"3248\ \char"3249\ \char"324A\ \char"324B\ \char"324C\
^^^^3280 ^^^^3281 ^^^^3282 ^^^^3283 ^^^^3284
^^^^^1f229 ^^^^^1f214 ^^^^^1f22a
\end{document}
使用 XELATEX 或 LuaLATEX 編譯,效果如下:
xunicode-addon
宏包
在實際使用中,無論是依靠碼位,還是藉由輸入法直接錄入這些特殊字元,都不是很方便。在 xunicode-addon
宏包(從屬於 xeCJK
)中,\textcircled
等一系列命令被重新定義,從而能夠顯示 Unicode 所分配的帶圈數字(和字母等)。舉例如下:
\documentclass{article}
\usepackage{fontspec,xunicode-addon}
\setmainfont{Source Han Serif SC}
\begin{document}
\textcircled{1}
\textcircled{25}
\textcircled{a}
\textcircled{Z}
\end{document}
利用 LATEX3 語法也可以迅速寫出如下循環而不傷身體:
\ExplSyntaxOn
\cs_set:Npn \TESTi
{
\int_step_inline:nnn { 0 } { 25 } { \textcircled{##1} ~ } \par
\int_step_inline:nnn { 26 } { 50 } { \textcircled{##1} ~ } \par
}
\cs_set:Npn \TESTii
{ \tl_map_inline:nn { abcdefghijklmnopqrstuvwxyz } { \textcircled{##1} ~ } \par }
\cs_set:Npn \TESTiii
{ \tl_map_inline:nn { ABCDEFGHIJKLMNOPQRSTUVWXYZ } { \textcircled{##1} ~ } \par }
\ExplSyntaxOff
\TESTi
\TESTii
\TESTiii
當然,其他樣式的帶圈數字並沒有提供快捷的輸入方式。
在 ctex
宏集中使用
以上的案例都是在標準文檔類 article
中搭配 fontspec
宏包完成的。如果切換成 ctex
宏集,則需要額外做一些調整。
對於中文文檔,我們通常需要為中西文(「西文」主要指 Latin script)分別設置字體。上面已經提到過,帶圈數字分散在了幾個 Unicode 區塊中。xeCJK
將其中的 Enclosed CJK Letters and Months 和 Enclosed Ideographic Supplement 設置為了 CJK 字元類,使用中文字體;其餘則為 Default 字元類,使用西文字體。
LuaTEX 下的情況類似,但稍顯複雜。首先是 luatexja
作出了 ALchar 和 JAchar 的劃分,大致相當於西文和日文(AL=ALphabetic,JA=JApanese);同時又預定義了一些字元範圍。默認設置中,上文所列的所有帶圈數字均會使用日文字體。其後,ctex
宏集為了適應中文排版的需求又做了一些修改。結果是,Enclosed Alphanumerics 被設置為了 ALchar,即使用西文字體。
總而言之,在 ctex
宏集的默認配置下:
Unicode 區塊 | XELATEX | LuaLATEX |
---|---|---|
Enclosed Alphanumerics | 西文 | 西文 |
Dingbats | 西文 | 西文 |
Enclosed CJK Letters and Months | 中文 | 中文 |
Enclosed Alphanumeric Supplement | 西文 | 西文 |
Enclosed Ideographic Supplement | 中文 | 西文 |
在 XELATEX 下,可以做如下修改:
% 使用中文字體
\xeCJKDeclareCharClass{CJK}{%
"24EA, % ⓪
"2460->"2473, % ①–⑳
"3251->"32BF, % ㉑–㊿
"24FF, % ⓿
"2776->"277F, % ❶–❿
"24EB->"24F4 % ⓫–⓴
}
\setCJKmainfont{Source Han Serif SC}
% 或使用西文字體
% \xeCJKDeclareCharClass{Default}{%
% "24EA, "2460->"2473, "3251->"32BF,
% "24FF, "2776->"277F, "24EB->"24F4}
% \setmainfont{Garamond-Math.otf}
在 LuaLATEX 下,也完全類似:
% 使用中文字體
\ltjdefcharrange{6}{%
"24EA, "2460-"2473, "3251-"32BF,
"24FF, "2776-"277F, "24EB-"24F4}
\setCJKmainfont{Source Han Serif SC}
% 或使用西文字體
% \ltjdefcharrange{3}{%
% "24EA, "2460-"2473, "3251-"32BF,
% "24FF, "2776-"277F, "24EB-"24F4}
% \setmainfont{Garamond-Math.otf}
這裡的 6
和 3
原先分別對應日文字元和西文標點、符號。還需注意範圍的寫法與 xeCJK
中不同。
配合 xunicode-addon
宏包,在 ctex
宏集中也同樣可以使用 \textcircled
命令輸入預定義的帶圈數字。但需注意,\textcircled
會預先檢查字元是否存在,且僅在西文字體中進行。所以如需使用中文字體進行顯示,就要「指鹿為馬」:[2]
% XeLaTeX 下需要把全體帶圈數字都設置成 Default 類
% LuaLaTeX 下無須額外設置
\xeCJKDeclareCharClass{Default}{"24EA, "2460->"2473, "3251->"32BF}
% 將中文字體聲明為(西文)字體族
\newfontfamily\EnclosedNumbers{Source Han Serif SC}
% 放置鉤子,只讓帶圈字元才需更換字體
\AtBeginUTFCommand[\textcircled]{\begingroup\EnclosedNumbers}
\AtEndUTFCommand[\textcircled]{\endgroup}
對於字體中沒有的帶圈數字,\textcircled
也能夠自動生成(由圓圈和相應的數字拼合)。選擇合適的字體之後,便可做一些比較暴力的嘗試:
即使是三位數,效果也尚能接受。
OpenType 的 nalt
特性
在 OpenType 中,有一項名為 nalt
(Alternate Annotation Forms)的 GSUB 特性,它的作用是把特定的字元形替換成符號標註形式(notational forms)。不少日文字體都包含這一特性,我們可以利用 fontspec
宏包提供的相關選項調用。舉例如下:
\documentclass{article}
\usepackage{fontspec}
\setmainfont{ipaexm.ttf} % IPAex 明朝,TeX Live 自帶
\begin{document}
{\addfontfeature{Annotation=0}123456789}
{\addfontfeature{Annotation=1}123456789}
{\addfontfeature{Annotation=2}123456789}
\end{document}
需要注意的是,Annotation=X
中的某個 X
具體對應何種樣式,這是由字體設計者決定的。此外,在一些字體中,部分假名、漢字也有類似的標註形式,可以用相同方法使用:
\documentclass{ctexart}
\setCJKmainfont{Hiragino Mincho Pro W3}
\begin{document}
{\addCJKfontfeature{Annotation=0}あア}
{\addCJKfontfeature{Annotation=1}かカ}
{\addCJKfontfeature{Annotation=2}さサ}
{\addCJKfontfeature{Annotation=3}たタ}
{\addCJKfontfeature{Annotation=4}なナ}
{\addCJKfontfeature{Annotation=5}はハ}
{\addCJKfontfeature{Annotation=6}まマ}
\end{document}
這裡我們用 \addCJKfontfeature
代替了 \addfontfeature
。此處作為演示的字體是 macOS 自帶的ヒラギノ明朝,在 Windows/Linux 上可換用其他字體。
Adobe-Japan1-7
Adobe-Japan1-7 字符集定義了更多的帶圈數字,很多樣式都支援 0–100 的數字範圍。但由於 Unicode 沒有為它們分配碼位,我們必須用 CID(Character IDentifier)來指定。[3]
由於 CID 到具體字元的映照比較複雜,因而這裡我們提供了一個宏包 textcircle-cid
,用來通過 CID 調用帶圈數字。textcircle-cid
宏包提供了下面一組命令:
\CIDtextcircled
\CIDtextblackcircled
\CIDtextboxed
\CIDtextblackboxed
\CIDtextrboxed
\CIDtextblackrboxed
支援的數字範圍是 0–100 和 00–09。XETEX、LuaTEX 和 upTEX 這三種 Unicode 引擎均可使用,但需要配合其他宏包及命令以實現正確的字體調用:
-
XELATEX 下需要通過
\setmainfont
等命令設置字體 -
LuaLATEX 下需要通過
\setmainjfont
等命令設置(日文)字體 -
upLATEX 下需要調用
pxchfon
宏包,並且使用\setminchofont
等命令設置字體,具體可以參考以下示例:% test-uptex.tex \documentclass{ujarticle} \usepackage{pxchfon,textcircle-cid} \setminchofont{KozMinPr6N-Regular.otf} \setgothicfont{KozGoPr6N-Regular.otf} \def\TEST{% \CIDtextcircled{0} \CIDtextblackcircled{1} \CIDtextboxed{00} \CIDtextblackboxed{10} \CIDtextrboxed{50} \CIDtextblackrboxed{100}} \begin{document} \textmc{\TEST} \par \textgt{\TEST} \end{document}
注意 upTEX 不直接生成 PDF,因此編譯時可採取如下方式:
uplatex test-uptex && dvipdfmx test-uptex
在上面的示例中,我們使用的字體是 Adobe 的小塚明朝和小塚ゴシック。事實上,只有遵從 Adobe-Japan1 的字體,才能利用 CID 正確地調用相應的字元。
字體的選擇
上文我們多次提及,帶圈數字的具體使用與字體密切相關。下面我們整理了 TEX Live 自帶的、可使用帶圈數字的字體,以及對應的數字範圍:
字體 | 帶圈 | 反白 | 無襯線 | 無襯線反白 |
---|---|---|---|---|
Baekmuk Batang/Dotum/Gulim/Headline | 1–15 | |||
Carlito | 0–20 | 0–20 | ||
DejaVuSans | 1–10 | 1–10 | 1–10 | 1–10 |
FreeMono, FreeSans | 1–10 | |||
FreeSerif | 1–10 | 1–10 | 1–10 | 1–10 |
Garamond Math | 0–50 | 0–20 | ||
IPAGothic, IPAMincho | 1–50 | 1–20 | ||
Junicode | 0–20 | 0–20 | ||
Lato | 0–20 | 0–20 | ||
Libertinus Serif/Sans/Math, Linux Libertine, Linux Biolinum | 0–20 | 0–20 | ||
Libertinus Keyboard, Linux Biolinum Keyboard | 1–10 | |||
STIX, STIX Math | 0–9 | 1–10 | 1–10 | |
STIX Two Math | 0–20 | 0–20 | 1–10 | 1–10 |
UnBatang, UnDinaru, UnDotum, UnGraphic, UnGungseo, UnJamoBatang, UnJamoDotum, UnJamoNovel, UnJamoSora, UnPen, UnPenheulim, UnPilgi, UnPilgia, UnShinmun, UnVada, UnYetgul | 0–20 | |||
XITS, XITS Math | 0–9 | 1–10 | 1–10 | |
文鼎PL簡報宋、文鼎PL簡中楷 | 1–10 |
以下是其他一些常見中、日文字體,其中很多是作業系統自帶的:
字體 | 帶圈 | 反白 | 無襯線 | 無襯線反白 |
---|---|---|---|---|
思源宋體、思源黑體 | 0–50 | 0–20 | 0–10 | 0–10 |
微軟雅黑、微軟正黑 | 1–10 | |||
蘋方 | 0–50 | 0–20 | 0–10 | 1–10 |
方正書宋、方正黑體、方正楷體、方正仿宋、等線 | 1–10 | |||
宋體、黑體、楷體、仿宋(中易) | 1–10 | |||
更紗黑體 (Sarasa Gothic) | 0–50 | 0–20 | 0–10 | 0–10 |
小塚明朝 (Kozuka Mincho)、小塚ゴシック (Kozuka Gothic) | 0–100 | 0–100 | ||
游明朝 (Yu Mincho)、游ゴシック (Yu Gothic) | 0–100 | 0–100 | ||
メイリオ (Meiryo) | 0–50 | 1–20 | 0–10 | 1–10 |
這裡我們用了 Python 腳本 check-circled-number.py
來讀取字體資訊,它還依賴 FontForge。注意由於字體版本不同,不保證表中所列結果與實際情況完全一致。
注釋
- ^在本頁面的 CSS 中,帶圈數字將優先使用思源宋體(Source Han Serif)顯示,但具體結果仍然取決於字體的安裝情況以及瀏覽器的渲染方式。
- ^感謝 @qinglee 的指導!見 CTeX-org/ctex-kit #399。
- ^感謝 @clerkma 的指導!見 CTeX-org/forum #20。