这是一个后续问题:我如何知道我的文档中使用了哪些连字符?
为了知道我可能会考虑禁用哪些连字符(我想到的是microtype
命令\DisableLigatures
;有关选择性禁用连字符的一些重要说明,请参见这个问题),了解可能应用哪些连字符将非常有用。我的文档中使用的字体提供哪些连字符?
答案1
下面介绍了 pdftex 和 Type 1 字体的解决方案。由于 TeX 不提供将连字分解为其组成字符的任何可能性(这些信息在它们被连字替换后会丢失),因此我们必须采取相反的方法:我们循环遍历字体中的所有字形对,将它们排版在临时框中,然后通过 etex 测试\lastnodetype
我们是否已获得连字。然后,我们可以将连字字符的槽号写入文件log
和/或实际排版连字及其部分,而连字的槽号仅在 中可用\showbox
(见下文)。
\RequirePackage{fix-cm}
\documentclass[12pt]{article}
\usepackage[LY1,T1]{fontenc}
\usepackage{fixltx2e}[2006/09/13]
\usepackage[expansion=false]{microtype}
\usepackage{yfonts}
% enable microtype's no ligatures procedure, without actually disabling any ligatures
\DisableLigatures{encoding = }
\makeatletter
\showboxbreadth100
\showboxdepth100
\newcount\MT@ligcount
\newbox\MT@ligbox
\newtoks\MT@ligtoks
\def\MT@showligs{%
\MT@info@nl{showing ligatures in font `\MT@@font'}%
\let\lig@temp\@empty
% loop over all glyph pairs in the font
\MT@do@font{%
%\iffontchar\MT@font\@tempcnta\relax % only test those glyphs that
\ifnum\tagcode\MT@font\@tempcnta=\@ne % have a "lig/kern program"
\MT@ligcount\z@
\loop
\iffontchar\MT@font\MT@ligcount
\setbox\@tempboxa\hbox{\MT@font
\setbox\MT@ligbox\hbox{\char\@tempcnta\char\MT@ligcount}%
\unhbox\MT@ligbox
\ifnum\lastnodetype=7 % ligature
\aftergroup\@firstofone
\else
\aftergroup\@gobble
\fi
}%
{% info in the log file
%\showbox\@tempboxa
\MT@info@nl{\the\@tempcnta\space + \the\MT@ligcount}%
% store information for later
\edef\lig@temp{\lig@temp
\noexpand\char\the\@tempcnta\noexpand\char\the\MT@ligcount
$($\noexpand\char\the\@tempcnta$^{[\the\@tempcnta]}$%
\noexpand\char\the\MT@ligcount$^{[\the\MT@ligcount]}),$ }%
}%
\fi
\advance\MT@ligcount\@ne
\ifnum\MT@ligcount < \@cclvi \repeat
\fi
}%
\ifx\lig@temp\@empty
\edef\lig@temp{\noexpand\normalfont No ligatures in `\MT@@font'.}
\else
\edef\lig@temp{\noexpand\normalfont Ligatures in `\MT@@font': \MT@font\lig@temp}%
\fi
\global\MT@ligtoks\expandafter\expandafter\expandafter
{\expandafter\the\expandafter\MT@ligtoks\lig@temp\par}%
}
% hook into microtype to make sure that all fonts are caught
\let\MT@noligatures@orig\MT@noligatures
\def\MT@noligatures{\MT@noligatures@orig\MT@showligs}
\AtEndDocument{\par\hrule\the\MT@ligtoks}
\begin{document}
Selecting
{\fontencoding{LY1}\selectfont various}
\textit{(including $\mathrm{maths}$)}
\textfrak{fonts:}
\end{document}
取消注释该\showbox
行将允许以笨拙的方式找出连字的槽号,它将以如下形式呈现:
> \box12=
hbox(5.1654+0.0)x11.74713
.T1/cmr/m/n/12 ^^V (ligature ^^U-)
这里显示了三重连字符 — ( emdash
),由连字符 – ( endash
) 和字符 - ( hyphen
) 组成,通常写为---
,其中^^V
= 22,且^^U
= 21 (转换规则这里)。除此之外,获取连字的槽号需要离开 pdftex 领域并依靠检查tfm
文件(参见@egreg 的解决方案)、使用 metapost(@AndrewKepert)或(可能)luatex。
答案2
如果您有.tfm
基础字体,即经典字体之一,您可以检查该文件。假设您想了解pplr8t
(Palatino Roman,T1 编码)。然后您可以运行此 shell 命令
tftopl pplr8t.tfm > pplr8t.pl
在pplr8t.pl
文件中,查找LIGTABLE
;这是文件开头附近的一大块。如果您运行 grep 搜索,例如
egrep '\(LABEL|LIG|STOP\)' pplr8t.pl
你会得到
(LIGTABLE
(LABEL O 25)
(LIG O 55 O 26)
(STOP)
(LABEL O 33)
(LIG C i O 36)
(LIG C l O 37)
(STOP)
(LABEL O 40)
(STOP)
(LABEL O 41)
(LIG O 140 O 275)
(STOP)
(LABEL O 47)
(LIG O 47 O 21)
(STOP)
(LABEL O 54)
(LIG O 54 O 22)
(STOP)
(LABEL O 55)
(LIG O 55 O 25)
(LIG O 177 O 177)
(STOP)
(LABEL O 74)
(LIG O 74 O 23)
(STOP)
(LABEL O 76)
(LIG O 76 O 24)
(STOP)
(LABEL O 77)
(LIG O 140 O 276)
(STOP)
(LABEL C A)
(STOP)
(LABEL C F)
(STOP)
(LABEL C L)
(STOP)
(LABEL C P)
(STOP)
(LABEL C R)
(STOP)
(LABEL C T)
(STOP)
(LABEL C V)
(STOP)
(LABEL C W)
(STOP)
(LABEL C Y)
(STOP)
(LABEL O 140)
(LIG O 140 O 20)
(STOP)
(LABEL C f)
(LIG C i O 34)
(LIG C f O 33)
(LIG C l O 35)
(STOP)
(LABEL C r)
(STOP)
(LABEL C v)
(STOP)
(LABEL C w)
(STOP)
(LABEL C y)
(STOP)
(LABEL O 200)
(STOP)
(LABEL O 201)
(STOP)
(LABEL O 210)
(STOP)
(LABEL O 212)
(STOP)
(LABEL O 217)
(STOP)
(LABEL O 220)
(STOP)
(LABEL O 224)
(STOP)
(LABEL O 225)
(STOP)
(LABEL O 230)
(STOP)
(LABEL O 300)
(STOP)
(LABEL O 301)
(STOP)
(LABEL O 302)
(STOP)
(LABEL O 303)
(STOP)
(LABEL O 304)
(STOP)
(LABEL O 305)
(STOP)
(LABEL O 335)
(STOP)
(LIG O 55 O 26)
(LIG C i O 36)
(LIG C l O 37)
(LIG O 140 O 275)
(LIG O 47 O 21)
(LIG O 54 O 22)
(LIG O 55 O 25)
(LIG O 177 O 177)
(LIG O 74 O 23)
(LIG O 76 O 24)
(LIG O 140 O 276)
(LIG O 140 O 20)
(LIG C i O 34)
(LIG C f O 33)
(LIG C l O 35)
相关块的形式如下
(LABEL O 41)
(LIG O 140 O 275)
(STOP)
这意味着字符“八进制 41”(即!
)后跟“八进制 140”(即`
)应该更改为字体位置“八进制 275”的字符。
相似地,
(LABEL C f)
(LIG C i O 34)
(LIG C f O 33)
(LIG C l O 35)
(STOP)
表示f
后面跟着的i
字符变为“八进制 34”位置中的字符,后面跟着的字符f
变为“八进制 33”,后面跟着的字符变为l
“八进制 35”。还有一个“八进制 33”的条目:
(LABEL O 33)
(LIG C i O 36)
(LIG C l O 37)
(STOP)
因此组合ffi
首先变成“八进制 33”,然后变成“八进制 36”。
如果你想禁用“ffl”连字,你必须告诉microtype
删除以“octal 33”开头的连字,这可以这样做
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\catcode`\^^[=12 % for technical reasons
\DisableLigatures[^^[]{encoding=T1}
\begin{document}
ffl ffi
\end{document}
由于“八进制 33”不可打印,因此必须使用低级技巧来指定它(^^[
,因为的字符代码[
是“八进制 133”)。这个\catcode
技巧是因为 LaTeX 默认将所有不可打印的字符声明为无效。
但是,您无法使用此microtype
方法来禁用ffl
并保留ffi
。
答案3
关于上述评论
“不幸的是,我不知道如何从排版文本中找出连字符的槽号。”
我想我确实知道一种方法 - 它们可以从 dvi 中提取出来。由于 dvi 的可读性不强,我知道的最简单的方法是使用 metapost,它可以很轻松地生成 tex 文件,将它们排版为 dvi,输入 dvi,分解图片并进行分析。这可能不是最好的方法!
以下是快速而粗略的版本:
input TEX
pair pt[];
string s[],temp_fname;
picture lig[][];
string fontname;
fontname="cmbx12";
minchar:=0;
maxchar:=127;
def charcount(expr obj)=
begingroup
if (textual obj):
(length textpart obj)
elseif (picture obj) and (length(obj)>0) :
(for $ within obj: charcount($) + endfor 0)
else: 0
fi
endgroup
enddef;
def charcodelist(expr obj)=
begingroup save s; string s;
if (textual obj):
s:=textpart obj;
(for i=0 upto (length s)-1:
decimal(ASCII(substring(i,i+1) of s)) &
endfor ""
)
elseif (picture obj) and (length(obj)>0) :
(for $ within obj: charcodelist($) & endfor "")
else:
""
fi
endgroup
enddef;
% quickly generate a file with all possible character pairs, then read it back in
temp_fname:=jobname&"-temp.mp";
write "verbatimtex \font\myfont="&fontname&"etex" to temp_fname;
for i = minchar upto maxchar:
for j = minchar upto maxchar:
write "lig["&decimal(i)&"]["&decimal(j)&"]:=btex \myfont\char"&decimal(i)&"\char"&decimal(j)&" etex;"
to temp_fname;
endfor
endfor
write EOF to temp_fname;
scantokens ("input "&temp_fname)
beginfig(1)
draw TEX("Ligatures in "&fontname) shifted (0,20);
pt0:=origin;
for i = minchar upto maxchar:
for j = minchar upto maxchar:
if charcount(lig[i][j])=1:
draw char(i) infont fontname shifted pt0;
draw decimal(i) infont "cmr10" shifted (pt0+20right);
draw char(j) infont fontname shifted (pt0+50right);
draw decimal(j) infont "cmr10" shifted (pt0+70right);
draw lig[i][j] shifted (pt0+100right);
draw charcodelist(lig[i][j]) infont "cmr10" shifted (pt0+120right);
pt0:=pt0+20down;
fi
endfor
endfor
endfig;
bye
产生如下输出:
答案4
这里http://www.gust.org.pl/projects/pearls/2005p/index_html(测试两个字符是否形成连字,作者 Petr Olšák)我们可以找到一个完美的两个字符的解决方案:
\newif\ifligature
\def\testligature #1#2{\setbox0=\hbox{%
\thickmuskip=1000mu \textfont0=\the\font
$\mathchar`#1 \mathrel\mathchar`#2$}%
\ifdim\wd0>500pt \ligaturefalse \else \ligaturetrue \fi}
添加循环很容易。