4

I need all uppercase letters with diacritics to have the same height (depth) of the corresponding naked uppercase letter.

Motivation: obtaining a regular baseline grid when stretching the baseline is not an option.

Here is an MWE to tinker with

\documentclass{standalone}

\usepackage[utf8]{inputenc}

\let\oldAcute\' \def\'#1{\protect\vphantom{#1}\smash{\oldAcute#1}}     % 1)
\let\oldHacek\v \def\v#1{\protect\vphantom{#1}\smash{\oldHacek#1}}     % 2)
\DeclareUnicodeCharacter{00C7}{\protect\vphantom{C}\smash{\c C}}       % 3)

\setlength\fboxsep{0pt}
\let\MU\MakeUppercase

\begin{document}
  \fbox{\fbox{A}\fbox{Á}\fbox{\'{A}}\fbox{\MU{á}}\fbox{\MU{\'{a}}}}
  \fbox{\fbox{C}\fbox{Č}\fbox{\v{C}}\fbox{\MU{č}}\fbox{\MU{\v{c}}}}
  \fbox{\fbox{C}\fbox{Ç}\fbox{\c{C}}\fbox{\MU{ç}}\fbox{\MU{\c{c}}}}
\end{document}

ZE REZULT

My document is UTF8 encoded, so the method of example 3) would suffice. Drawbacks:

  • diacritics put with macros are not affected
  • compilation of a long list of commands is necessary

It's feasible. But I'd like to not worry about using macros. Also, I am using a number greater than two of languages fraught with diacritics. Writing the list is going to get annoying.

(Q1) Can at least this last task be automated? (Q2) Even just knowing a general method to recover the naked letter from the accented character (or its unicode id) would be a step forward.

Another tentative solution is presented by example 2). Seemingly working in all the situations I'd need, it's actually rubbish as shown by counterexample 1). (Remember, my document is UTF8 encoded.)

(Q3) Does a fix to 1) exist?

I also tried some cut&stitch on the \accent primitive, to no avail.

(Q4) Does another way better than what I could think of exist?

I'm using LaTeX, and I'd like to stay with it. A sleek solution running on any another engine would be interesting to see, naturally!

  • 3
    In well designed fonts, accents are already placed so as to avoid collision with surrounding text. E.g., compare é and É in EB Garamond: the accent on É is shorter — not so much that casual readers notice, but just short enough to keep the text tidy. If accented capitals cause a problem in your document and you can’t increase the leading from the default, you have the wrong font for the job. It would be better to omit diacriticals on capitals (as was often done with metal type) than to smash them, because when the leading is too small for the content, your readers will have difficulty. – Thérèse Aug 2 '15 at 3:01
  • 1
    Note that using constructed characters is not good in various ways. They will not look quite right in many cases and may not be searchable/copy-pastable/other good things. (This changes based on various things, including progress, so may or may not be significant.) That is, you really should be using the T1 encoding. If this is for body text, you definitely should be. Even in diagrams, say, the text will not look as good as it might. – cfr Aug 2 '15 at 3:04
  • 2
    In a sense, the question is odd since using accents ought not to be stretching your baseline in the first place. So if it is, something is wrong. – cfr Aug 2 '15 at 3:06
  • 1
    A text where, for some reasons, there are many diacritics above capitals should be typeset with a slightly increased baseline distance. – egreg Aug 2 '15 at 8:08
  • @egreg That is exactly what I first thought, and how I initially solved the issue. Unfortunately, I'm not the one having the last word on the document. – Paolo Brasolin Aug 2 '15 at 8:23
7

First of all, you absolutely need to tell whoever is in charge of the project what you’re almost saying in the comments: what you’re asking to do here is the consequence of bad decisions that you shouldn’t have to deal with. All you’re doing here is working around these bad decisions because you can’t tackle the main issue.

Now, as long as you’re aware of that, your workaround 3 is really easy to do using the Unicode character database (see also the detailed description), because it has the decomposition mappings. The following script, in Lua, does just that (provided you have UnicodeData.txt in the current directory). You can process it with texlua (not plain Lua because it needs the lpeg library).

local P, C, Ct = lpeg.P, lpeg.C, lpeg.Ct
local semicolon = P';'
local field = C((1 - semicolon)^1)
local linepatt = field * (semicolon * field)^0

local space = P' '
local singlechar = C((1 - space)^1)
local ltsign = P'<'
local initchar = C((1 - space - ltsign)^1)
local nfdpatt = Ct(initchar * (space * singlechar)^0)

texaccents = {
    ['0300'] = '\\`',
    ['0301'] = "\\'",
    ['0302'] = '\\^',
    ['0303'] = '\\~',
    ['0308'] = '\\"',
    ['030B'] = '\\H',
    ['030A'] = '\\r',
    ['030C'] = '\\v',
    ['0306'] = '\\u',
    ['0304'] = '\\=',
    ['0307'] = '\\.',
    ['0328'] = '\\k'
}
for line in io.lines('UnicodeData.txt') do
  local usv, _, _, _, _, nfd = linepatt:match(line)
  if nfd then
    local chars = nfdpatt:match(nfd)
    if chars and #chars > 1 then
      local base = chars[1]
      smashedchr = '\\char"' .. base
      for i = 2, #chars do
        local diac = texaccents[chars[i]]
        if diac then
          smashedchr = diac .. '{' .. smashedchr .. '}'
        else
          break
        end
      end

      print('\\DeclareUnicodeCharacter{' .. usv .. '}{\\protect\\vphantom{\\char"' .. base .. '}\\smash{' .. smashedchr .. '}}')
    end
  end
end

Here are the first few lines it outputs:

\DeclareUnicodeCharacter{00C0}{\protect\vphantom{\char"0041}\smash{\`{\char"0041}}}
\DeclareUnicodeCharacter{00C1}{\protect\vphantom{\char"0041}\smash{\'{\char"0041}}}
\DeclareUnicodeCharacter{00C2}{\protect\vphantom{\char"0041}\smash{\^{\char"0041}}}
\DeclareUnicodeCharacter{00C3}{\protect\vphantom{\char"0041}\smash{\~{\char"0041}}}
\DeclareUnicodeCharacter{00C4}{\protect\vphantom{\char"0041}\smash{\"{\char"0041}}}
\DeclareUnicodeCharacter{00C5}{\protect\vphantom{\char"0041}\smash{\r{\char"0041}}}

Note that the base characters are included using \char and not directly because it was easier to do so; I can change it later.

  • Thanks. Hopefully this will be a temporary solution. On a side note: I noticed \vphantom breaks paragraphs if it's the first object. It's better to just use a \strut. It also needs no protection, so \DeclareUnicodeCharacter{...}{\strut\smash{...}} works fine. – Paolo Brasolin Aug 4 '15 at 7:28
  • You’re welcome. I’ll amend the code. – Arthur Reutenauer Aug 4 '15 at 11:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.