在 LuaLaTeX 中,Dagesh 不能独立于希伯来字母着色

在 LuaLaTeX 中,Dagesh 不能独立于希伯来字母着色

基于这个问题,我设法将不同的希伯来语变音符号(称为 niqqud 和 teamim)分别着色。然而,最近我发现这只适用于元音和吟唱符号,而不适用于达格什或者胫/辛点。我犯了错误吗?

请参阅下面的结果和示例代码(字母内的点应该是黄色):

在此处输入图片描述

\documentclass{minimal}
\usepackage{luacolor}
\usepackage[nil,bidi=basic]{babel}
\babelprovide[import=he,main]{hebrew}
\babelfont[hebrew]{rm}[Renderer=Harfbuzz,Script=Hebrew,Language=Default]{Times New Roman}

\begin{document}

\textcolor{blue}{ב}\textcolor{yellow}{ּ}\textcolor{red}{ָ}\textcolor{green}{֑}

\end{document}

答案1

正如 Cicada 在评论中指出的那样,这是因为字体整形器将 Unicode 字符序列 0x05D1(bet)和 0x05BC(dages)转换为 0xFB31,因此 dagesh 的颜色属性消失了,并且您无法通过简单的 pdf 颜色规范对字形进行部分着色,您需要剪切或重新绘制部分字形(比如说只绘制基本字母)。

一个想法是有两个 ב,第一个将是黄色并形成连字符,第二个将是蓝色并与第一个重叠。

据我所知,涉及变音符号的连字不会改变字符的位置和宽度,所以它应该可以起作用。

这是一个简单的例子(我减少了一些前言,babel 可以处理其他事情)。

\documentclass{article}
\usepackage{luacolor}
\usepackage[provide=*,bidi=basic,hebrew]{babel}
\babelfont{rm}[Renderer=Harfbuzz]{Times New Roman}

\newcommand*\dagesh[1]{\leavevmode\rlap{\textcolor{yellow}{#1^^^^05bc}}\textcolor{blue}{#1}}

\begin{document}
\dagesh ב\textcolor{red}{ָ}\textcolor{green}{֢}
\end{document}

在此处输入图片描述

如果我们将其与没有颜色的字形进行比较,我们会发现它们完美重叠

\documentclass{article}
\usepackage{luacolor}
\usepackage[provide=*,bidi=basic,hebrew]{babel}
\babelfont{rm}[Renderer=Harfbuzz]{Times New Roman}

\newcommand*\dagesh[1]{\leavevmode\rlap{\textcolor{yellow}{#1^^^^05bc}}\textcolor{blue}{#1}}

\begin{document}
\dagesh ב\textcolor{red}{ָ}\textcolor{green}{֢}\llap{בָּ֢}
\end{document}

在此处输入图片描述

这种方法有两个主要问题。首先,我们使用的水平框可能会破坏正确的字距调整,其次,源代码几乎不可读,因此让我们尝试改进这两个问题。

我们可以使用 lua 回调为要选择的字符分配颜色属性,而不必手动为每个字形着色。对于此示例,我的目标是将所有基本字母涂成蓝色,将所有 nikud、maqaf 和 sof passuq 涂成红色,将 teamim 涂成绿色,最后将 dagesh、shin dot 和 sin dot 涂成黄色。

为此,我们将基本字母涂成蓝色,连字将根据涉及该连字的变音符号着色,teamim 涂成绿色,nikud 涂成红色。

以下函数将在每个连字后插入一个等于其宽度和该连字的基本字母的负字距,并分配一个适当的颜色属性,以便 luacolor 稍后对其进行着色。

\pagecolor和选项twocolumn只是为了获得更好的图片

\documentclass[twocolumn]{article}
\usepackage{luacolor}
\usepackage[provide=*,bidi=basic,hebrew]{babel}
\babelfont{rm}[Renderer=Harfbuzz]{Times New Roman}

\directlua{
local traverse = node.traverse
local glyph = node.id('glyph')
local set_attribute = node.set_attribute
local has_attribute = node.has_attribute
local insert_after = node.insert_after
local node_new = node.new
local getvalue = oberdiek.luacolor.getvalue
local red = "1 0 0 rg 1 0 0 RG"
local green = "0 1 0 rg 0 1 0 RG"
local blue = "0 0 1 rg 0 0 1 RG"
local yellow = "1 1 0 rg 1 1 0 RG"

local chars = { }

for char = 0x5d0, 0x05f2 do % base letters
    chars[char] = {color = blue}
end
for char = 0x0591, 0x05af do % teamim
    chars[char] = {color = green}
end
for char = 0x05b0, 0x05c7 do % nikud
    chars[char] = {color = red}
end
for char = 0xfb30, 0xfb4a do % dagesh ligatures
    chars[char] = {color = yellow, base = char - 0xf560}
end
for char = 0xfb2a, 0xfb2d do % shin dot ligatures
    chars[char] = {color = yellow, base = 0x05e9}
end

chars[0x05bc] = {color = yellow} % dagesh
chars[0x05f3] = {color = blue} % geresh
chars[0x05f4] = {color = blue} % gershyim
chars[0xfb1d] = {color = red, base = 0x05d9} % yod + hiriq
chars[0xfb1d] = {color = red, base = 0x05f2} % yod yod + patah
chars[0xfb20] = {color = blue} % alt ayin
chars[0xfb2e] = {color = red, base = 0x05d0} % alef patah
chars[0xfb2f] = {color = red, base = 0x05d0} % alef qamats
chars[0xfb4b] = {color = red, base = 0x05d5} % vav holam
chars[0xfb4c] = {color = red, base = 0x05d1} % bet rafa
chars[0xfb4d] = {color = red, base = 0x05db} % kaf rafa
chars[0xfb4e] = {color = red, base = 0x05e4} % pe rafa
chars[0xfb4f] = {color = blue} % alef + lamed

chars[1180354] = {color = red, base = 0x05da} % ???
chars[1180355] = {color = red, base = 0x05da} % ???
chars[1180356] = {color = red, base = 0x05dc} % ???

local function color_char(hlist)
    for n in traverse(hlist) do
        local id = n.id
        if id == glyph then
            local char =  n.char
            local data = chars[char]
            if data then
                local color = data.color
                if color then
                    local color_val = getvalue(color)
                    local color_attr = luatexbase.attributes["LuaCol@Attribute"]
                    set_attribute(n, color_attr, color_val)
                end
                local base = data.base
                if base then
                    local newn = node_new("glyph")
                    newn.font = font.current()
                    newn.char = base
                    %
                    local startactual = node_new("whatsit", "pdf_literal")
                    startactual.data = "/Span<</ActualText<>>>BDC"
                    startactual.mode = 1
                    %
                    local endactual = node_new("whatsit", "pdf_literal")
                    endactual.data = "EMC"
                    endactual.mode = 1
                    %
                    local newk = node_new("kern")
                    newk.kern = -newn.width
                    %
                    insert_after(hlist,n,newk)
                    insert_after(hlist,newk,startactual)
                    insert_after(hlist,startactual,newn)
                    insert_after(hlist,newn,endactual)
                end
            end
        end
    end
end

luatexbase.add_to_callback('pre_linebreak_filter',
    function(h)
        color_char(h)
        return true
    end,
'color_char')
luatexbase.add_to_callback('hpack_filter',
    function(h)
        color_char(h)
        return true
    end,
'color_char')
}

\begin{document}
\pagecolor{black}\noindent
וּֽבְקֻצְרְכֶם֙ אֶת־קְצִ֣יר אַרְצְכֶ֔ם לֹ֧א תְכַלֶּ֛ה פְּאַ֥ת שָׂדְךָ֖ לִקְצֹ֑ר וְלֶ֥קֶט קְצִֽירְךָ֖ לֹ֥א תְלַקֵּֽט׃
וְכַרְמְךָ֙ לֹ֣א תְעוֹלֵ֔ל וּפֶ֥רֶט כַּרְמְךָ֖ לֹ֣א תְלַקֵּ֑ט לֶֽעָנִ֤י וְלַגֵּר֙ תַּעֲזֹ֣ב אֹתָ֔ם אֲנִ֖י יְהֹוָ֥ה אֱלֹהֵיכֶֽם׃
וְלֹֽא־תִשָּׁבְע֥וּ בִשְׁמִ֖י לַשָּׁ֑קֶר וְחִלַּלְתָּ֛ אֶת־שֵׁ֥ם אֱלֹהֶ֖יךָ אֲנִ֥י יְהֹוָֽה׃
לֹֽא־תַעֲשֹׁ֥ק אֶת־רֵֽעֲךָ֖ וְלֹ֣א תִגְזֹ֑ל לֹֽא־תָלִ֞ין פְּעֻלַּ֥ת שָׂכִ֛יר אִתְּךָ֖ עַד־בֹּֽקֶר׃
לֹא־תְקַלֵּ֣ל חֵרֵ֔שׁ וְלִפְנֵ֣י עִוֵּ֔ר לֹ֥א תִתֵּ֖ן מִכְשֹׁ֑ל וְיָרֵ֥אתָ מֵּאֱלֹהֶ֖יךָ אֲנִ֥י יְהֹוָֽה׃
לֹא־תַעֲשׂ֥וּ עָ֙וֶל֙ בַּמִּשְׁפָּ֔ט לֹא־תִשָּׂ֣א פְנֵי־דָ֔ל וְלֹ֥א תֶהְדַּ֖ר פְּנֵ֣י גָד֑וֹל בְּצֶ֖דֶק תִּשְׁפֹּ֥ט עֲמִיתֶֽךָ׃
לֹא־תֵלֵ֤ךְ רָכִיל֙ בְּעַמֶּ֔יךָ לֹ֥א תַעֲמֹ֖ד עַל־דַּ֣ם רֵעֶ֑ךָ אֲנִ֖י יְהֹוָֽה׃
לֹֽא־תִשְׂנָ֥א אֶת־אָחִ֖יךָ בִּלְבָבֶ֑ךָ הוֹכֵ֤חַ תּוֹכִ֙יחַ֙ אֶת־עֲמִיתֶ֔ךָ וְלֹא־תִשָּׂ֥א עָלָ֖יו חֵֽטְא׃
לֹֽא־תִקֹּ֤ם וְלֹֽא־תִטֹּר֙ אֶת־בְּנֵ֣י עַמֶּ֔ךָ וְאָֽהַבְתָּ֥ לְרֵעֲךָ֖ כָּמ֑וֹךָ אֲנִ֖י יְהֹוָֽה׃
\end{document}

在此处输入图片描述

几点说明。

  • 该函数在字体整形器之后调用,这通常不推荐,但在这种情况下,我们需要为连字符分配颜色,这仅在该阶段之后存在。

  • 连字符后插入的每个基本字母都用/ActualText跨度包裹,这样从 PDF 中提取文本时就不会被考虑。

  • 此时,有些字形不再是 unicode 字符。我不确定它们的字符代码是什么意思。

  • 示例文本取自这个答案,内容与此主题相同。

  • 如果您想要不同颜色的 shin dot 和 dagesh,则必须重叠三个字形。每个颜色一个字形。

答案2

您可以添加一个字距来阻止 harfbuzz 组合蓝色区域中的字形,但是这会弄乱下方重音符号的定位,因此您需要另一个字距来进行补偿。

在此处输入图片描述

\documentclass{minimal}
\usepackage{luacolor}
\usepackage[nil,bidi=basic]{babel}
\babelprovide[import=he,main]{hebrew}
\babelfont[hebrew]{rm}[Renderer=Harfbuzz,Script=Hebrew,Language=Default]{Times New Roman}

\begin{document}

\textcolor{blue}{ב}\kern 0pt\textcolor{yellow}{ּ}\kern-2pt\textcolor{red}{ָ}\textcolor{green}{֑}

\end{document}

相关内容