粉碎所有大寫字元上的變音符號

粉碎所有大寫字元上的變音符號

我需要所有帶有變音符號的大寫字母與相應的裸大寫字母具有相同的高度(深度)。

動機:在拉伸基線時無法獲得規則的基線網格。

這是一個需要修改的 MWE

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

澤結果

我的文件是UTF8編碼的,所以範例的方法3)就足夠了。缺點:

  • 與宏一起放置的變音符號不受影響
  • 需要編譯一長串命令

這是可行的。但我不想擔心使用巨集。另外,我使用的語言超過兩種,並且充滿了變音符號。寫這個清單會變得很煩人。

Q1)至少最後一項任務可以自動化嗎? (Q2)即使只是知道從重音字元(或其 unicode id)恢復裸字母的通用方法也會向前邁出一步。

透過例子給了另一種嘗試性的解決方案2)。看起來可以在我需要的所有情況下工作,但實際上是垃圾,如反例所示1)。 (請記住,我的文件是 UTF8 編碼的。)

第三季)是否存在修復1)

我還嘗試了對原語進行一些切割和縫合\accent,但無濟於事。

第四季)是否存在比我能想到的更好的方法?

我正在使用LaTeX,並且我想繼續使用它。 當然,在任何其他引擎上運行的時尚解決方案都會很有趣!

答案1

首先,你絕對需要告訴負責該專案的人你在評論中幾乎要說的話:你在這裡要求做的是你不應該處理的錯誤決定的後果。你在這裡所做的就是解決這些錯誤的決定,因為你無法解決主要問題。

現在,只要您意識到這一點,您的解決方法 3 就可以輕鬆使用Unicode字元資料庫(也可以看看詳細描述),因為它具有分解映射。下面的 Lua 腳本就是這樣做的(前提是UnicodeData.txt在目前目錄中)。您可以使用texlua(不是普通的 Lua,因為它需要lpeg庫)來處理它。

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

以下是它輸出的前幾行:

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

請注意,使用 和 不直接包含基本字符,\char因為這樣做更容易;我可以稍後更改。

相關內容