typo-fkr.lmt /size: 3892 b    last modification: 2025-02-21 11:03
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 fontdata      = fonts.hashes.identifiers
16local getkernpair   = fonts.handlers.otf.getkern
17
18local insertbefore  = nuts.insertbefore
19local new_kern      = nuts.pool.fontkern
20
21local enableaction  = nodes.tasks.enableaction
22
23local glyph_code  <const> = nodes.nodecodes.glyph
24
25local a_extrakern <const> = attributes.private("extrafontkern")
26
27-- 0=none 1=min 2=max 3=mixed
28
29typesetters.fontkerns = { }
30
31function typesetters.fontkerns.handler(head)
32    local current   = head
33    local lastfont  = nil
34    local lastchar  = nil
35    local lastdata  = nil
36    while current do
37        local char, font = isglyph(current)
38        if char then
39            local a = getattr(current,a_extrakern)
40            if a then
41                if font ~= lastfont then
42                    if a > 0 and lastchar then
43                        if not lastdata then
44                            lastdata = fontdata[lastfont]
45                        end
46                        local kern  = nil
47                        local data  = fontdata[font]
48                        local kern1 = getkernpair(lastdata,lastchar,char)
49                        local kern2 = getkernpair(data,lastchar,char)
50                        if a == 1 then
51                            kern = kern1 > kern2 and kern2 or kern1 -- min
52                        elseif a == 2 then
53                            kern = kern1 > kern2 and kern1 or kern2 -- max
54                        else -- 3
55                            kern = (kern1 + kern2)/2                -- mixed
56                        end
57                        if kern ~= 0 then
58                            head = insertbefore(head,current,new_kern(kern))
59                        end
60                        lastdata = data
61                    else
62                        lastdata = nil
63                    end
64                elseif lastchar then
65                    if not lastdata then
66                        lastdata = fontdata[lastfont]
67                    end
68                    local kern = getkernpair(lastdata,lastchar,char)
69                    if kern ~= 0 then
70                        head = insertbefore(head,current,new_kern(kern))
71                    end
72                end
73                lastchar = char
74                lastfont = font
75            elseif lastfont then
76                lastfont = nil
77                lastchar = nil
78                lastdata = nil
79            end
80        elseif lastfont then
81            lastfont = nil
82            lastchar = nil
83            lastdata = nil
84        end
85        current = getnext(current)
86    end
87    return head
88end
89
90do
91
92    local variables    = interfaces.variables
93    local enabled      = false
94    local setattribute = tex.setattribute
95
96    local unsetvalue <const> = attributes.unsetvalue
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