当未定义或不可用时替换小型大写字母

当未定义或不可用时替换小型大写字母

根据这个问题的精彩答案可以检查小写字母是否可用。但是,尝试实际使用此代码时,我得到了一个奇怪的结果:当字体形状不明确的替换按预期进行。当字体形状为无法使用测试表明字体形状可用,但 Latex 却使用替代品。

有没有办法使用\fakedsc罗马版本而不是普通的无衬线小型大写字母?

在下面的代码中,你可以看到当使用T1/lmr/bx/sc和时,小写字母会被替换(两者都是T1/lmss/bx/sc不明确的)但不是什么时候T1/lmss/m/sc使用(无法使用):

\documentclass{scrartcl} 

\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage{relsize}
\usepackage{etoolbox}

\newcommand{\fakedsc}[3][1]{#2\begingroup\smaller[#1]{\MakeUppercase{#3}}\endgroup}

\makeatletter
\def\define@newfont{%
    \begingroup
    \let\typeout\@font@info
    \escapechar\m@ne
    \expandafter\expandafter\expandafter
    \split@name\expandafter\string\font@name\@nil
    \try@load@fontshape % try always
    \expandafter\ifx
    \csname\curr@fontshape\endcsname \relax
    \expandafter\gdef\csname \curr@fontshape/sub\endcsname{}% new      
    \wrong@fontshape\else
    \extract@font\fi
    \endgroup}

\newcommand\testsc[3][1]{%
    \ifcsname \f@encoding/\f@family/\f@series/sc/sub\endcsname
    no \fakedsc[#1]{#2}{#3}
    \else 
    \ifcsname \f@encoding/\f@family/\f@series/sc\endcsname  yes \textsc{#2#3} \else no \fakedsc[#1]{#2}{#3} \fi
    \fi   
    }
\makeatother

\begin{document}

    \detokenize{\rmfamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est} => test successful, no replacement

    {\bfseries
    \detokenize{\rmfamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est}} => test successful, replaced

    \sffamily
    \detokenize{\sffamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est} => test \textbf{not successful}, auto replacement

    {\bfseries
    \detokenize{\sffamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est}} => test successful, replaced

\end{document}

结果显示如下: 替换

编辑:我发现了一些有用的东西source2e 文档。第 166 页顶部写道:

如果 \curr@fontshape 组合不可用(即未定义),我们将调用宏 \wrong@fontshape 来处理这种情况。否则 \extract@font 将为我们加载外部字体。

341 % \expandafter\ifx

342 % \csname\curr@fontshape\endcsname \relax

343 \try@load@fontshape % 总是尝试

344 % \fi

345 \expandafter\ifx

346 \csname\curr@fontshape\endcsname \relax

347 \错误@fontshape\else

为了允许替换,我们调用 curr@fontshape 宏,它通常会扩展为 \relax 但可能包含替换代码(参见 \subst@fontshape 定义)。

348 % \csname\curr@fontshape\endcsname

349 \提取@字体\fi

我们几乎已经完成,只需关闭该组即可恢复 \escapechar。

350

...所以魔法词是不明确的,这意味着字体形状的解决方案无法使用(根据 LaTeX 警告仍然需要)。

编辑2:

据我所理解,\testsc测试替换(这会导致警告“字体形状T1/lmr/bx/sc未定义(字体)使用T1/lmr/bx/n改用“如果\textsc使用)。然后,它测试字体形状是否存在。出于某些原因,这个测试对于T1/lmss/m/sc虽然是肯定的,但对于\textsc它还是给出了警告“字体T1/lmss/m/sc大小 <10.95> 不可用(字体) 字体形状T1/lmr/m/sc已尝试使用字体形状“。这个案例是否需要额外测试? 与第一个警告相反,我无法找出这个警告是如何产生的。我在字体安装指南看起来,在测试完成之前,该系列已经发生了变化,仅在这种情况下。

编辑3:

我仔细观察了“无法使用“警告。原来这是由t1lmss.fd(位于 MiKTeX 2.9/tex/latex/lm)。除了其他替换之外,它还声明:

\DeclareFontShape{T1}{lmss}{m}{sc}
{<->sub*lmr/m/sc}{}

通过在序言中添加以下代码,我能够将替换更改为无衬线字体的正常形状。

\documentclass{scrartcl} 

\usepackage[utf8]{inputenc}
\usepackage{lmodern} \sffamily\selectfont
\usepackage[T1]{fontenc}
\usepackage{relsize}
\usepackage{etoolbox}

\DeclareFontShape{T1}{lmss}{m}{sc}
{<->sub*lmss/m/n}{}
\normalfont
...

这是新的输出: 新的替代者

是否有可能对这种替代进行测试,或者“取消声明”它无需处理 .fd 文件

免责声明: 我知道伪造小型大写字母会出现问题,但使用不同的字体对我来说并不是解决办法。

答案1

最后一步编辑3其实很简单:从t1lmss.fd并删除 tex 文件本身中不需要的代码。因此,字体形状的声明被覆盖,同时保持原始 fd 文件完好无损。完整的 tex 文件如下所示:

\documentclass{scrartcl} 

\usepackage[utf8]{inputenc}
\usepackage{lmodern} %\sffamily\selectfont % (not needed if the whole fd file is inserted, which uses \DeclareFontFamily{T1}{lmss}{})
\usepackage[T1]{fontenc}
\usepackage{relsize}
\usepackage{etoolbox}

%%% taken from the .fd file (MiKTeX 2.9\tex\latex\lm\t1lmss.fd) -- this overrides the definitions in the fd file while leaving the original file untouched
\DeclareFontFamily{T1}{lmss}{}
\DeclareFontShape{T1}{lmss}{m}{n}
{<-8.5> ec-lmss8
    <8.5-9.5> ec-lmss9      <9.5-11>  ec-lmss10
    <11-15.5> ec-lmss12     <15.5-> ec-lmss17
}{}
\DeclareFontShape{T1}{lmss}{m}{it}
{<->ssub*lmss/m/sl}{}
\DeclareFontShape{T1}{lmss}{m}{sl}
{<-8.5> ec-lmsso8
    <8.5-9.5> ec-lmsso9      <9.5-11>  ec-lmsso10
    <11-15.5> ec-lmsso12     <15.5-> ec-lmsso17
}{}
%%%%%%% Font/shape undefined, therefore substituted
%\DeclareFontShape{T1}{lmss}{m}{sc}     % <-- deleted
%{<->sub*lmr/m/sc}{}                    % <-- deleted
\DeclareFontShape{T1}{lmss}{b}{n}
{<->ssub * lmss/bx/n}{}
\DeclareFontShape{T1}{lmss}{b}{sl}
{<->ssub * lmss/bx/sl}{}
\DeclareFontShape{T1}{lmss}{b}{it}
{<->ssub * lmss/bx/it}{}
%%%%%%%% semibold condensed series
\DeclareFontShape{T1}{lmss}{sbc}{n}
{<-> ec-lmssdc10}{}
\DeclareFontShape{T1}{lmss}{sbc}{sl}
{<-> ec-lmssdo10}{}
\DeclareFontShape{T1}{lmss}{sbc}{it}
{<->ssub*lmss/sbc/sl}{}
%%%%%%%%% bold extended series
\DeclareFontShape{T1}{lmss}{bx}{n}
{<-> ec-lmssbx10}{}
\DeclareFontShape{T1}{lmss}{bx}{sl}
{<-> ec-lmssbo10}{}
\DeclareFontShape{T1}{lmss}{bx}{it}
{<->ssub*lmss/bx/sl}{}
%%% end of fd file
\normalfont

\newcommand{\fakedsc}[3][1]{#2\begingroup\smaller[#1]{\MakeUppercase{#3}}\endgroup}

\makeatletter
\def\define@newfont{%
    \begingroup
    \let\typeout\@font@info
    \escapechar\m@ne
    \expandafter\expandafter\expandafter
    \split@name\expandafter\string\font@name\@nil
    \try@load@fontshape % try always
    \expandafter\ifx
    \csname\curr@fontshape\endcsname \relax
    \expandafter\gdef\csname \curr@fontshape/sub\endcsname{}% new      
    \wrong@fontshape\else
    \extract@font\fi
    \endgroup}

\newcommand\testsc[3][1]{%
    \ifcsname \f@encoding/\f@family/\f@series/sc/sub\endcsname
    no \fakedsc[#1]{#2}{#3}
    \else 
    \ifcsname \f@encoding/\f@family/\f@series/sc\endcsname  yes \textsc{#2#3} \else no \fakedsc[#1]{#2}{#3} \fi
    \fi   
    }
\makeatother

\begin{document}

    \detokenize{\rmfamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est} => test successful, no replacement

    {\bfseries
    \detokenize{\rmfamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est}} => test successful, replaced

    \sffamily
    \detokenize{\sffamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est} => test finally successful, \detokenize{\fakedsc} used!!!

    {\bfseries
    \detokenize{\sffamily} \textsc{Test} -- \testsc{T}{ested} -- without \fakedsc{T}{est}} => test successful, replaced

\end{document}

正如你所看到的,\sffamily \textsc{Test}现在给出了一个警告,字体形状未定义

未定义警告

但是,如果\textsc{Test}删除所有部分,则不会显示任何警告。如果需要的话,也许甚至可以警告使用了伪造的小写字母(对我来说,不需要)。

甚至更好:\sffamily \testsc{Tested}没有给予作为答案(意味着字体形状是没有定义的\fakedsc并按预期用途:

成功替换

这是一项艰苦的工作,但我很高兴我终于找到了答案。如果有更简洁的解决方案,我很乐意了解它。

免责声明:

使用此解决方案需要您自行负责,并且只有您能够接受可怕结果。

相关内容