6

I am using arev package for a scientific LaTeX article (compiling using pfdlatex) and would like to use small caps for certrain proper names. On the internet I found a code

\def\fauxschelper#1#2\relax{%
    \ifnum`#1>``\ifnum`#1<`\{\scalebox{.87}[.79]{\uppercase{#1}}\else#1\fi\else#1\fi%
    \ifx\relax#2\relax\else\fauxschelper#2\relax\fi}
\newcommand\fauxsc[1]{\fauxschelper#1\relax\relax}

which looks kind of nice, but doesn’t work when I try to use unicode characters with UTF-8 encoding. It seems to try to interpret the unicode characters byte-wise rather than character-wise.

Since I need especially umlauts to work properly, I tried something else using the etoolbox package:

\documentclass{scrartcl}

% GENERAL STUFF - ENCODING, LANGUAGE
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}

% GENERAL STUFF - FONT
\usepackage{arev}

% GENERAL STUFF - GRAPHICS
\usepackage{graphicx}
\usepackage{etoolbox}

% DEPENDS ON GRAPHICX PACKAGE (WHICH CAN BE USEPACKAGE'd LATER)
% ESSENTIALLY YOU JUST NEED TO TAKE A LOOK WHETHER \uppercase{\next} IS THE SAME AS \next. Use scalebox on the uppercase'd letter if not.
\makeatletter
\newcommand{\fsc}[1]{%
    \@tfor\next:=#1\do{%
        \edef\temp@up{\uppercase{\next}}%
        \ifdefstrequal{\temp@up}{\next}{\next}{\scalebox{.87}[.79]{\uppercase{\next}}}%
    }%
}
\makeatother

\begin{document}
The \fsc{Schr{ö}dinger} equation is \dots
\end{document}

This produces the text „Schrödinger“, where each letter is in the case specified in the \fsc command and scaled with a \scalebox. The expected result would be that the comparison yields true if a character is equal to its uppercase form (so if it represents an uppercase letter) and false otherwise, so that it yields an uppercase unscaled letter S and uppercase scaled letters CHRÖDINGER.

I suppose my problem has something to do with the order in which TeX evaluates commands, but since I’m very new to programming LaTeX macros, I have no idea how to fix this.

What would also be nice is a way of coding the command to prevent having to write multi-byte characters in braces.

3
  • 1
    \uppercase is not expandable. You can use \tl_upper_case:n from expl3.
    – Manuel
    Commented Nov 24, 2015 at 13:51
  • 2
    do you have to use utf8? If you used latin1 then all (supported) characters are single byte and things are a lot easier. Commented Nov 24, 2015 at 14:17
  • I don’t need need to use UTF-8, but I’ve used it in all other files so far and I would like to stick with it, because I’m often using characters that are not contained in Latin1 and would have to be paraphrased otherwise.
    – Toshiki
    Commented Nov 24, 2015 at 15:30

4 Answers 4

6

Highly inefficient and no real substitute for true small caps (my suggestion is to avoid faking small caps at all costs). All common accents are covered, others can be added.

\documentclass{scrartcl}

% GENERAL STUFF - ENCODING, LANGUAGE
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}

% GENERAL STUFF - FONT
\usepackage{arev}

% GENERAL STUFF - GRAPHICS
\usepackage{graphicx}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\fsc}{m}
 {
  \toshiki_fsc:n { #1 }
 }

\tl_new:N \l_toshiki_input_tl

\cs_set_eq:Nc \toshiki_tl_set_protecteded_x:Nn { protected@edef }

\cs_new_protected:Nn \toshiki_fsc:n
 {
  \toshiki_tl_set_protecteded_x:Nn \l_toshiki_input_tl { #1 }
  \regex_replace_all:nnN { ([a-z]+) } { \c{toshiki_fake_sc:n}\cB\{\1\cE\} } \l_toshiki_input_tl
  \regex_replace_all:nnN { (\c{[r"'`^]})\c{toshiki_fake_sc:n}\cB. }
                         { \c{toshiki_fake_sc:n}\cB\{\1 } \l_toshiki_input_tl
  \regex_replace_all:nnN { (\c{ae|oe|ss}) } { \c{toshiki_fake_sc:n}\cB\{\1\cE\} } \l_toshiki_input_tl
  \tl_use:N \l_toshiki_input_tl
 }

\cs_new_protected:Nn \toshiki_fake_sc:n
 {
  \scalebox{.87}[.79]{ \MakeUppercase{#1} }
 }
\ExplSyntaxOff

\begin{document}

The \fsc{Schr{ö}dinger} equation is \dots

\fsc{Hôpital} \fsc{Ångström} \fsc{ångström} \fsc{ŒœÆæß}

\fsc{Some Wörds To Be In Småll Cáps}

\end{document}

enter image description here

3
  • My concern is not so much with efficiency of the process and more about a convienient solution that yields a good-looking final result. Compile time is through the roof already, because I include a lot of graphics and some chemical formulae. (I use chemfig, which is really cool, but also very slow.)
    – Toshiki
    Commented Nov 24, 2015 at 15:34
  • @Toshiki It is not good looking, sorry. But it just depends on the faked small caps.
    – egreg
    Commented Nov 24, 2015 at 15:34
  • 1
    @Toshiki There is a library in the TikZ universe \usetikzlibrary{external} which precompiles the figures. This way I reduces my (very long) compile time to a few seconds, because it just included the precompiled figures. Just do a big compile when you edit your figures. It isn't directly applicable here, but maybe it helps you anyway :-).
    – WalyKu
    Commented Nov 24, 2015 at 21:02
3

If you need this "fake small caps" only for names and only for single words (note that spaces don't work in your solution) then you can prepare a simple macro \fcs which keeps the first letter unchanged and the rest is uppercased and scaled.

\def\fsc#1{\fscA#1\relax}
\def\fscA#1#2\relax{#1\scalebox{.87}[.79]{\uppercase{#2}}}

test: \fsc{Schrödinger} equation.

If the first letter is accented then you must to enclose it into braces because LaTeX treats badly with UTF-8 codes (if you are using csplain then this problem doesn't occur).

3

An approximation. If unicode characters appear not in minuscules, it doesn't work correctly. May be there's a solution with \str_case:nnF but you should do it manually, or just use LuaTeX (or XeTeX).

\documentclass{scrartcl}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}

\usepackage{arev}

\usepackage{xparse} % loads expl3
\usepackage{etoolbox}
\usepackage{graphicx}
\usepackage{textcase} % to get \MakeTextUppercase

\ExplSyntaxOn
\NewDocumentCommand \fsc { m } { \toshiki_fsc:n { #1 } }
\cs_new_protected:Npn \toshiki_fsc:n #1
 {
  \tl_map_inline:nn { #1 }
   {
    \str_if_eq:eeTF { ##1 } { \text_uppercase:n { ##1 } }
     { ##1 }
     { \scalebox{.87}[.79]{ \toshiki_fsc_aux:n { ##1 } } }
   }
 }
\cs_new_protected:Npn \toshiki_fsc_aux:n #1 { \MakeTextUppercase { #1 } }
\ExplSyntaxOff

\begin{document}
The \fsc{Schr{ö}dinger} equation is\dots\ \fsc{Schr{Ö}dinger} doesn't work, though\dots
\end{document}

but if you redefine \toshiki_fsc_aux:n with

\cs_new_protected:Npn \toshiki_fsc_aux:n #1
 {
  \str_case:nnTF { #1 }
   {
    {Ö}{}
    {Á}{}
    % etc.
   }
   { #1 }
   { \scalebox{.87}[.79]{ \MakeTextUppercase { #1 } } }
 }
\cs_new_protected:Npn \toshiki_fsc_aux:n #1
 {
  \tl_if_in:nnTF { ÖÁ } { #1 }
   { #1 }
   { \scalebox{.87}[.79]{ \MakeTextUppercase { #1 } } }
 }

then it does work, but you have to add the characters manually.

By the way, this is a messy solution, with patches here and there…

1

I suggest another solution of the problem of processing the macro argument "character per character" when UTF-8 code and \usepackage{inputenc} is used. You can compare the simplicity of mine solution with others presented here.

Suppose, that you have set \usepackage[T1]{fontenc} and \usepackage[utf8]{inputenc}. Then the UTF-8 codes expand to simple tokens with respect to T1 encoding and the \lccode are set to T1 encoding too. Then you can do this:

\def\fsc#1{\edef\tmp{#1}\expandafter\fscA\tmp\relax}
\def\fscA#1{%
   \ifx#1\relax \else
      \ifnum\lccode`#1=`#1 (small:\char\uccode`#1)\else (cap:#1)\fi
      \expandafter\fscA
\fi
}

A test: \fsc{Schrödinger} equation.
2
  • Well, mine also copes with spaces (yours doesn't) and also accepts \fsc{Abc \emph{def}}.
    – egreg
    Commented Nov 25, 2015 at 11:02
  • And with OT1 you're doomed, of course.
    – egreg
    Commented Nov 25, 2015 at 11:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .