font-imp-ligatures.lmt /size: 4410 b    last modification: 2024-01-16 10:22
1if not modules then modules = { } end modules ['font-imp-ligatures'] = {
2    version   = 1.001,
3    comment   = "companion to font-ini.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
9-- Not perfect (disc) but we have allternatives.
10
11local lpegmatch = lpeg.match
12local utfsplit = utf.split
13local settings_to_array = utilities.parsers.settings_to_array
14
15local fonts              = fonts
16local otf                = fonts.handlers.otf
17local registerotffeature = otf.features.register
18local addotffeature      = otf.addfeature
19
20-- This is a quick and dirty hack.
21
22local lookups = { }
23local protect = { }
24local revert  = { }
25local zwjchar = 0x200C
26local zwj     = { zwjchar }
27
28addotffeature {
29    name    = "blockligatures",
30    type    = "chainsubstitution",
31    nocheck = true, -- because there is no 0x200C in the font
32    prepend = true, -- make sure we do it early
33    future  = true, -- avoid nilling due to no steps yet
34    lookups = {
35        {
36            type = "multiple",
37            data = lookups,
38        },
39    },
40    data = {
41        rules = protect,
42    }
43}
44
45addotffeature {
46    name     = "blockligatures",
47    type     = "chainsubstitution",
48    nocheck  = true,  -- because there is no 0x200C in the font
49    append   = true,  -- this is done late
50    overload = false, -- we don't want to overload the previous definition
51    lookups  = {
52        {
53            type = "ligature",
54            data = lookups,
55        },
56    },
57    data = {
58        rules = revert,
59    }
60}
61
62registerotffeature {
63    name        = 'blockligatures',
64    description = 'block certain ligatures',
65}
66
67-- local splitter = lpeg.splitat(":")
68--
69-- local function blockligatures(str)
70--     local t = settings_to_array(str)
71--     for i=1,#t do
72--         local ti = t[i]
73--         local before, current, after = lpegmatch(splitter,ti)
74--         if current and after then -- before is returned when no match
75--             -- experimental joke
76--             if before then
77--                 before = utfsplit(before)
78--                 for i=1,#before do
79--                     before[i] = { before[i] }
80--                 end
81--             end
82--             if current then
83--                 current = utfsplit(current)
84--             end
85--             if after then
86--                 after = utfsplit(after)
87--                 for i=1,#after do
88--                     after[i] = { after[i] }
89--                 end
90--             end
91--         else
92--             before  = nil
93--             current = utfsplit(ti)
94--             after   = nil
95--         end
96--         if #current > 1 then
97--             local one = current[1]
98--             local two = current[2]
99--             lookups[one] = { one, zwjchar }
100--             local one = { one }
101--             local two = { two }
102--             local new = #protect + 1
103--             protect[new] = {
104--                 before  = before,
105--                 current = { one, two },
106--                 after   = after,
107--                 lookups = { 1, false }, -- not shared !
108--             }
109--             revert[new] = {
110--                 current = { one, zwj },
111--                 after   = { two },
112--                 lookups = { 1, false }, -- not shared !
113--             }
114--         end
115--     end
116-- end
117
118local function blockligatures(str)
119    local t = settings_to_array(str)
120    for i=1,#t do
121        local ti = t[i]
122        local current = utfsplit(ti)
123        if #current > 1 then
124            local one = current[1]
125            local two = current[2]
126            lookups[one] = { one, zwjchar }
127            local one = { one }
128            local two = { two }
129            local new = #protect + 1
130            protect[new] = {
131                current = { one, two },
132                lookups = { 1, false }, -- not shared !
133            }
134            revert[new] = {
135                current = { one, zwj },
136                after   = { two },
137                lookups = { 1, false }, -- not shared !
138            }
139        end
140    end
141end
142
143-- blockligatures("\0\0")
144
145otf.helpers.blockligatures = blockligatures
146
147-- blockligatures("fi,ff")
148-- blockligatures("fl")
149
150if context then
151
152    interfaces.implement {
153        name      = "blockligatures",
154        arguments = "string",
155        actions   = blockligatures,
156    }
157
158end
159