Quebrando diacríticos em todos os caracteres maiúsculos

Quebrando diacríticos em todos os caracteres maiúsculos

Preciso que todas as letras maiúsculas com diacríticos tenham a mesma altura (profundidade) da letra maiúscula nua correspondente.

Motivação: obter uma grade de linha de base regular ao esticar a linha de base não é uma opção.

Aqui está um MWE para mexer

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

ZÉ REZULT

Meu documento é codificado em UTF8, então o método do exemplo 3)seria suficiente. Desvantagens:

  • os diacríticos colocados com macros não são afetados
  • é necessária a compilação de uma longa lista de comandos

É viável. Mas eu gostaria de não me preocupar em usar macros. Além disso, estou usando um número maior que dois de idiomas repletos de diacríticos. Escrever a lista vai ser chato.

(1º trimestre) Pelo menos esta última tarefa pode ser automatizada? (2º trimestre) Mesmo conhecer um método geral para recuperar a letra nua do caractere acentuado (ou seu id unicode) seria um passo à frente.

Outra solução provisória é apresentada pelo exemplo 2). Aparentemente trabalhando em todas as situações que eu preciso, na verdade é um lixo, como mostra counterexample 1). (Lembre-se, meu documento é codificado em UTF8.)

(3º trimestre) Existe uma correção 1)?

Também tentei cortar e costurar no \accentprimitivo, sem sucesso.

(4º trimestre) Existe outra maneira melhor do que eu poderia imaginar?

Estou usando LaTeXe gostaria de continuar com ele. Uma solução elegante rodando em qualquer outro motor seria interessante de ver, naturalmente!

Responder1

Em primeiro lugar, é absolutamente necessário dizer ao responsável pelo projeto o que você está quase dizendo nos comentários: o que você está pedindo para fazer aqui é consequência de más decisões com as quais você não deveria ter que lidar. Tudo o que você está fazendo aqui é contornar essas decisões erradas porque não consegue resolver o problema principal.

Agora, desde que você esteja ciente disso, sua solução alternativa 3 é realmente fácil de executar usando oBanco de dados de caracteres Unicode(Veja tambéma descrição detalhada), porque possui os mapeamentos de decomposição. O script a seguir, em Lua, faz exatamente isso (desde que esteja UnicodeData.txtno diretório atual). Você pode processá-lo com texlua(não com Lua simples porque precisa da 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

Aqui estão as primeiras linhas que ele gera:

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

Observe que os caracteres base foram incluídos usando \chare não diretamente porque era mais fácil fazê-lo; Posso mudar isso mais tarde.

informação relacionada