summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-fkr.lua
blob: 1de554b5714890b02b902eba3fb90b3f485831d4 (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
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

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