summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-fkr.lua
blob: b235ff284ec788059ee9f42d69e0cf05abd7da8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
if not modules then modules = { } end modules ['typo-fkr'] = {
    version   = 1.001,
    comment   = "companion to typo-fkr.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local nuts          = nodes.nuts
local tonut         = nuts.tonut
local getid         = nuts.getid
local getnext       = nuts.getnext
local getchar       = nuts.getchar
local getfont       = nuts.getfont
local getattr       = nuts.getattr

local nodecodes     = nodes.nodecodes
local glyph_code    = nodecodes.glyph

local fontdata      = fonts.hashes.identifiers
local getkernpair   = fonts.handlers.otf.getkern

local insert_before = nuts.insert_before
local new_kern      = nuts.pool.fontkern

local a_extrakern   = attributes.private("extrafontkern")

-- 0=none 1=min 2=max 3=mixed

typesetters.fontkerns = { }

function typesetters.fontkerns.handler(head)
    local kepthead  = head
    local head      = tonut(head)
    local current   = head
    local lastfont  = nil
    local lastchar  = nil
    local lastdata  = nil
    local done      = false
    while current do
        local id = getid(current)
        if id == glyph_code then
            local a = getattr(current,a_extrakern)
            if a then
                local char = getchar(current)
                local font = getfont(current)
                if font ~= lastfont then
                    if a > 0 and lastchar then
                        if not lastdata then
                            lastdata = fontdata[lastfont]
                        end
                        local kern  = nil
                        local data  = fontdata[font]
                        local kern1 = getkernpair(lastdata,lastchar,char)
                        local kern2 = getkernpair(data,lastchar,char)
                        if a == 1 then
                            kern = kern1 > kern2 and kern2 or kern1 -- min
                        elseif a == 2 then
                            kern = kern1 > kern2 and kern1 or kern2 -- max
                        else -- 3
                            kern = (kern1 + kern2)/2                -- mixed
                        end
                        if kern ~= 0 then
                            head, current = insert_before(head,current,new_kern(kern))
                            done = true
                        end
                        lastdata = data
                    else
                        lastdata = nil
                    end
                elseif lastchar then
                    if not lastdata then
                        lastdata = fontdata[lastfont]
                    end
                    local kern = getkernpair(lastdata,lastchar,char)
                    if kern ~= 0 then
                        head, current = insert_before(head,current,new_kern(kern))
                        done = true
                    end
                end
                lastchar = char
                lastfont = font
            elseif lastfont then
                lastfont = nil
                lastchar = nil
                lastdata = nil
            end
        elseif lastfont then
            lastfont = nil
            lastchar = nil
            lastdata = nil
        end
        current = getnext(current)
    end
    return kepthead, done
end

if context then

    local variables    = interfaces.variables
    local unsetvalue   = attributes.unsetvalue
    local enabled      = false
    local setattribute = tex.setattribute

    local values       = {
        [variables.none ] = 0,
        [variables.min  ] = 1,
        [variables.max  ] = 2,
        [variables.mixed] = 3,
        [variables.reset] = unsetvalue,
    }

    local function setextrafontkerns(str)
        if not enabled then
            nodes.tasks.enableaction("processors","typesetters.fontkerns.handler")
            enabled = true
        end
        setattribute(a_extrakern,values[str] or unsetvalue)
    end

    interfaces.implement {
        name      = "setextrafontkerns",
        arguments = "string",
        actions   = setextrafontkerns,
    }

end