Rompiendo signos diacríticos en todos los caracteres en mayúsculas

Rompiendo signos diacríticos en todos los caracteres en mayúsculas

Necesito que todas las letras mayúsculas con signos diacríticos tengan la misma altura (profundidad) que la letra mayúscula desnuda correspondiente.

Motivación: obtener una cuadrícula de línea de base regular al estirar la línea de base no es una opción.

Aquí hay un MWE con el que jugar

\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

Mi documento está codificado en UTF8, por lo que el método del ejemplo 3)sería suficiente. Desventajas:

  • los signos diacríticos puestos con macros no se ven afectados
  • Es necesaria la compilación de una larga lista de comandos.

Es factible. Pero me gustaría no preocuparme por el uso de macros. Además, estoy utilizando un número mayor que dos en idiomas plagados de signos diacríticos. Escribir la lista va a resultar molesto.

(Q1) ¿Se puede automatizar al menos esta última tarea? (Q2) Incluso conocer un método general para recuperar la letra desnuda del carácter acentuado (o su identificación Unicode) sería un paso adelante.

Otra solución tentativa se presenta con un ejemplo 2). Aparentemente funciona en todas las situaciones que necesitaría, en realidad es una tontería, como lo muestra el contraejemplo 1). (Recuerde, mi documento está codificado en UTF8).

(Q3) ¿Existe una solución 1)?

También probé algunos cortes y puntadas en el \accentprimitivo, sin éxito.

(Q4) ¿Existe otra forma mejor que la que se me ocurre?

Estoy usando LaTeXy me gustaría seguir con él. Sería interesante ver una solución elegante que funcione con cualquier otro motor, ¡naturalmente!

Respuesta1

En primer lugar, es absolutamente necesario que le digas a quien está a cargo del proyecto lo que casi estás diciendo en los comentarios: lo que estás pidiendo aquí es la consecuencia de malas decisiones con las que no deberías tener que lidiar. Todo lo que estás haciendo aquí es solucionar estas malas decisiones porque no puedes abordar el problema principal.

Ahora, siempre que sea consciente de ello, la solución alternativa 3 es realmente fácil de realizar utilizando elBase de datos de caracteres Unicode(ver tambiénla descripción detallada), porque tiene las asignaciones de descomposición. El siguiente script, en Lua, hace precisamente eso (siempre que lo tenga UnicodeData.txten el directorio actual). Puedes procesarlo con texlua(no simplemente con Lua porque necesita la lpegbiblioteca).

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

Aquí están las primeras líneas que genera:

\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}}}

Tenga en cuenta que los personajes base se incluyen usando \chary no directamente porque fue más fácil hacerlo; Puedo cambiarlo más tarde.

información relacionada