typo-fkr.lmt /size: 3905 b    last modification: 2024-01-16 10:22
1if not modules then modules = { } end modules ['typo-fkr'] = {
2    version   = 1.001,
3    comment   = "companion to typo-fkr.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local nuts          = nodes.nuts
10local getid         = nuts.getid
11local getnext       = nuts.getnext
12local getattr       = nuts.getattr
13local isglyph       = nuts.isglyph
14
15local nodecodes     = nodes.nodecodes
16local glyph_code    = nodecodes.glyph
17
18local fontdata      = fonts.hashes.identifiers
19local getkernpair   = fonts.handlers.otf.getkern
20
21local insertbefore  = nuts.insertbefore
22local new_kern      = nuts.pool.fontkern
23
24local enableaction  = nodes.tasks.enableaction
25
26local a_extrakern   = attributes.private("extrafontkern")
27
28-- 0=none 1=min 2=max 3=mixed
29
30typesetters.fontkerns = { }
31
32function typesetters.fontkerns.handler(head)
33    local current   = head
34    local lastfont  = nil
35    local lastchar  = nil
36    local lastdata  = nil
37    while current do
38        local char, font = isglyph(current)
39        if char then
40            local a = getattr(current,a_extrakern)
41            if a then
42                if font ~= lastfont then
43                    if a > 0 and lastchar then
44                        if not lastdata then
45                            lastdata = fontdata[lastfont]
46                        end
47                        local kern  = nil
48                        local data  = fontdata[font]
49                        local kern1 = getkernpair(lastdata,lastchar,char)
50                        local kern2 = getkernpair(data,lastchar,char)
51                        if a == 1 then
52                            kern = kern1 > kern2 and kern2 or kern1 -- min
53                        elseif a == 2 then
54                            kern = kern1 > kern2 and kern1 or kern2 -- max
55                        else -- 3
56                            kern = (kern1 + kern2)/2                -- mixed
57                        end
58                        if kern ~= 0 then
59                            head = insertbefore(head,current,new_kern(kern))
60                        end
61                        lastdata = data
62                    else
63                        lastdata = nil
64                    end
65                elseif lastchar then
66                    if not lastdata then
67                        lastdata = fontdata[lastfont]
68                    end
69                    local kern = getkernpair(lastdata,lastchar,char)
70                    if kern ~= 0 then
71                        head = insertbefore(head,current,new_kern(kern))
72                    end
73                end
74                lastchar = char
75                lastfont = font
76            elseif lastfont then
77                lastfont = nil
78                lastchar = nil
79                lastdata = nil
80            end
81        elseif lastfont then
82            lastfont = nil
83            lastchar = nil
84            lastdata = nil
85        end
86        current = getnext(current)
87    end
88    return head
89end
90
91do
92
93    local variables    = interfaces.variables
94    local unsetvalue   = attributes.unsetvalue
95    local enabled      = false
96    local setattribute = tex.setattribute
97
98    local values       = {
99        [variables.none ] = 0,
100        [variables.min  ] = 1,
101        [variables.max  ] = 2,
102        [variables.mixed] = 3,
103        [variables.reset] = unsetvalue,
104    }
105
106    local function setextrafontkerns(str)
107        if not enabled then
108            enableaction("processors","typesetters.fontkerns.handler")
109            enabled = true
110        end
111        setattribute(a_extrakern,str and values[str] or unsetvalue)
112    end
113
114    interfaces.implement {
115        name      = "setextrafontkerns",
116        public    = true,
117        protected = true,
118        arguments = "optional",
119        actions   = setextrafontkerns,
120    }
121
122end
123