對齊

由於中文字體設計的緣故,中文的引號、括號、書名號等標點符號,它們的左半部分,例如左引號,在字符圖形空間是靠右側的。node

左引號

按照中文排版慣例,段落首行縮進兩個字符的寬度。可是,像左引號這樣的標點符號,當它出如今段落之首時,所體現的段落縮進在視覺上就會大於兩個字符的寬度。這樣的標點符號出如今段落中任何一行的行首,都會致使相似的問題。segmentfault

引號未與段落首行的左邊界對齊

在乎這樣的問題,可能會被嘲笑或被不覺得然國。不過,我不只在乎,並且用了大概一天的時間把它解決了。app

解決方法很簡單,就是在排版軟件完成了段落分行以後,寫個程序去檢查引號、括號、書名號等標點符號的左半部分是否是出如今了段落中每一行的開始,而後對符合這一狀況的文本行裏的字符位置進行微調。固然,前提是這個排版軟件支持這樣的程序。大多數是不支持的,不過,TeX 能夠。基於 TeX 的 ConTeXt MkIV 也能夠。因此,我纔有機會對這個問題的解決做一些記錄。ide

既然出如今行首的標點會致使縮進寬度在視覺上增大,消除這個增量的最簡單的辦法是,將這一行文本總體向左偏移,直到標點與段落左邊界對齊爲止,段落首行的左引號算是與段落左邊界近似齊平。字體

以左引號開頭的文本行總體向左偏移了 0.35 倍字符寬度

可是,將一行文本向作移動,確定會致使文本的右側出現空缺,這在上面的圖裏能夠看得出來。有一些拆東牆補西牆的意味。此時,因爲段落分行工做已經結束,所以沒有辦法再從下一行裏取字符去填補這一行右側的微小空缺;即便有辦法,也會產生連鎖反應,從而波及整個段落再度從新分行,這樣會讓問題變得很是複雜,甚至無解。lua

須要換個角度去思考。一行文本向左移動而引發的右側空缺,是由於最右側的字符被「坑」了。民主的作法是,這一行文本里的每一個字符都應該承擔一點空缺。能夠想象爲,將這行文本最右側的空缺打碎,將碎片插入到這一行文本的每一個字符的後面,從而使得該行文本總體向右有所膨脹。因爲每一個字符後面所分擔的空缺碎片很小,足以欺騙個人眼睛。spa

下面給出一個具備通常性的例子以及完整的試驗代碼:設計

\usemodule[zhfonts]
\setuppapersize[A5][A5]

\setupindenting[first,always,2em]
\setupinterlinespace[line=1.5em]

\startluacode
zhfonts = zhfonts or {}

local hlist = nodes.nodecodes.hlist
local glyph = nodes.nodecodes.glyph
local insert_before = node.insert_before
local insert_after = node.insert_after
local new_kern = nodes.pool.kern

local fonthashes = fonts.hashes
local fontdata   = fonthashes.identifiers
local quaddata   = fonthashes.quads

local left_puncs = {
    [0x2018] = 0.35, -- ‘
    [0x201C] = 0.35, -- 「
    [0x3008] = 0.35, -- 〈
    [0x300A] = 0.35, -- 《
    [0x300C] = 0.35, -- 「
    [0x300E] = 0.35, -- 『
    [0x3010] = 0.35, -- 【
    [0x3014] = 0.35, -- 〔
    [0x3016] = 0.35, -- 〖
    [0xFF08] = 0.35, -- (
    [0xFF3B] = 0.35, -- [
    [0xFF5B] = 0.35  -- {
}

local function is_left_punc(n)
    if left_puncs[n.char] then return true end
    return false
end

local function quad_multiple(font, r)
    local quad = quaddata[font]
    return r * quad
end

function zhfonts.align_left_puncs(head)
    local it = head
    while it do
        if it.id == hlist then
            local e = it.head
            local neg_kern = nil
            local hit = nil
            while e do
                if e.id == glyph then
                    if is_left_punc(e) then
                        hit = e
                    end
                    break
                end
                e = e.next
            end
            if hit ~= nil then
                -- 文本行總體向左偏移
                neg_kern = -left_puncs[hit.char] * quad_multiple(hit.font, 1)
                insert_before(head, hit, new_kern(neg_kern))
                -- 統計字符個數
                local w = 0
                local x = hit
                while x do
                    if x.id == glyph then w = w + 1 end
                    x = x.next
                end
                if w == 0 then w = 1 end
                -- 將 neg_kern 分攤出去
                x = it.head -- 從新遍歷
                av_neg_kern = -neg_kern/w
                local i = 0
                while x do
                    if x.id == glyph then
                        i = i + 1
                        -- 最後一個字符以後不插入 kern
                        if i < w then 
                            insert_after(head, x, new_kern(av_neg_kern))
                        end
                    end
                    x = x.next
                end
            end
        end
        it = it.next
    end
    return head, done
end
nodes.tasks.appendaction("finalizers", "after", "zhfonts.align_left_puncs")
\stopluacode

\starttext
\quotation{很遺憾,}最高執政官說,\quotation{若是沒有高級文明的培植,他們還要在亞光速和三維時空中被禁錮兩千年,至少還需一千年時間才能掌握和使用湮滅能量,兩千年後才能經過多維時空進行通信,至於經過超空間躍遷進行宇宙航行,多是五千年後的事了,至少要一萬年,他們才具有加入銀河系碳基文明你們庭的起碼條件。}

參議員說:\quotation{文明的這種孤獨進化,是銀河系太古時代纔有的事。若是那古老的記載正確,我那太古的祖先生活在一個海洋行星的深海中。在那黑暗世界中的無數個王朝後,一個龐大的探險計劃開始了,他們發射了第一個外空飛船,那是一個透明浮力小球,通過漫長的路程浮上海面。當時正是深夜,小球中的先祖第一次看到了星空……大家可以想象,那對他們是怎樣的壯麗和神祕啊!}

最高執政官說:\quotation{那是一個讓人想往的時代,一粒灰塵樣的行星對先祖都是一個無限廣闊的世界,在那綠色的海洋和紫色的草原上,先祖敬畏地面對羣星……這感受咱們已丟失千萬年了。}

\quotation{可我如今又找回了它!}參議員指着地球的影像說,她那藍色的晶瑩球體上浮動着雪白的雲紋,他以爲她真像一種來自他祖先星球海洋中的一種美麗的珍珠,\quotation{看這個小小的世界,她上面的生命體在過着本身的生活,作着本身的夢,對咱們的存在,對銀河系中的戰爭和毀滅全然不知,宇宙對他們來講,是但願和夢想的無限源泉,這真象一首來自太古時代的歌謠。}

他真的吟唱了起來,他們三人的智能場合爲一體,盪漾着玫瑰色的波紋。那從遙遠得沒法想象的太古時代傳下來的歌謠聽起來悠遠、神祕、蒼涼,經過超空間,它傳遍了整個銀河系,在這團由上千億顆恆星組成的星雲中,數不清的生命感到了一種久已消失的舒適和寧靜。

\quotation{宇宙的最不可理解之處在於它是能夠理解的。}最高執政官說。

\quotation{宇宙的最可理解之處在於它是不可理解的。}參議員說
\stoptext

如今,我已經將上述代碼中處理標點符號與段落左邊界對齊的代碼合併到 zhfonts 模塊 [1] 了,因此上例裏 \startluacode ... \stopluacode 裏的代碼是不須要的。code


[1] zhfonts:ConTeXt MkIV 中文支持的 Hackingblog

相關文章
相關標籤/搜索