luatex-fonts-ext.lua /size: 7260 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['luatex-fonts-ext'] = {
2    version   = 1.001,
3    comment   = "companion to luatex-*.tex",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9if context then
10    os.exit()
11end
12
13local byte = string.byte
14
15local fonts              = fonts
16local handlers           = fonts.handlers
17local otf                = handlers.otf
18local afm                = handlers.afm
19local registerotffeature = otf.features.register
20local registerafmfeature = afm.features.register
21
22-- extra generic stuff
23
24function fonts.loggers.onetimemessage() end
25
26-- done elsewhere
27--
28-- loadmodule('font-ext-imp-italic.lua')
29-- loadmodule('font-ext-imp-effect.lua')
30-- loadmodule('luatex-fonts-lig.lua')
31
32-- protrusion (simplified version)
33
34fonts.protrusions        = fonts.protrusions        or { }
35fonts.protrusions.setups = fonts.protrusions.setups or { }
36local setups             = fonts.protrusions.setups
37
38setups['default'] = { -- demo vector
39
40    factor   = 1,
41    left     = 1,
42    right    = 1,
43
44    [0x002C] = { 0, 1    }, -- comma
45    [0x002E] = { 0, 1    }, -- period
46    [0x003A] = { 0, 1    }, -- colon
47    [0x003B] = { 0, 1    }, -- semicolon
48    [0x002D] = { 0, 1    }, -- hyphen
49    [0x2013] = { 0, 0.50 }, -- endash
50    [0x2014] = { 0, 0.33 }, -- emdash
51    [0x3001] = { 0, 1    }, -- ideographic comma      、
52    [0x3002] = { 0, 1    }, -- ideographic full stop  。
53    [0x060C] = { 0, 1    }, -- arabic comma           ،
54    [0x061B] = { 0, 1    }, -- arabic semicolon       ؛
55    [0x06D4] = { 0, 1    }, -- arabic full stop       ۔
56
57}
58
59local function initializeprotrusion(tfmdata,value)
60    if value then
61        local setup = setups[value]
62        if setup then
63            local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1
64            local emwidth = tfmdata.parameters.quad
65            tfmdata.parameters.protrusion = {
66                auto = true,
67            }
68            for i, chr in next, tfmdata.characters do
69                local v, pl, pr = setup[i], nil, nil
70                if v then
71                    pl, pr = v[1], v[2]
72                end
73                if pl and pl ~= 0 then chr.left_protruding  = left *pl*factor end
74                if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end
75            end
76        end
77    end
78end
79
80local specification = {
81    name        = "protrusion",
82    description = "shift characters into the left and or right margin",
83    initializers = {
84        base = initializeprotrusion,
85        node = initializeprotrusion,
86    }
87}
88
89registerotffeature(specification)
90registerafmfeature(specification)
91
92-- expansion (simplified version)
93
94fonts.expansions        = fonts.expansions        or { }
95fonts.expansions.setups = fonts.expansions.setups or { }
96local setups            = fonts.expansions.setups
97
98setups['default'] = { -- demo vector
99
100    stretch     = 2,
101    shrink      = 2,
102    step        = .5,
103    factor      = 1,
104
105    [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
106    [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
107    [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
108    [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
109    [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
110    [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
111    [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
112    [byte('w')] = 0.7, [byte('z')] = 0.7,
113    [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
114}
115
116local function initializeexpansion(tfmdata,value)
117    if value then
118        local setup = setups[value]
119        if setup then
120            local factor = setup.factor or 1
121            tfmdata.parameters.expansion = {
122                stretch = 10 * (setup.stretch or 0),
123                shrink  = 10 * (setup.shrink  or 0),
124                step    = 10 * (setup.step    or 0),
125                auto    = true,
126            }
127            for i, chr in next, tfmdata.characters do
128                local v = setup[i]
129                if v and v ~= 0 then
130                    chr.expansion_factor = v*factor
131                else -- can be option
132                    chr.expansion_factor = factor
133                end
134            end
135        end
136    end
137end
138
139local specification = {
140    name        = "expansion",
141    description = "apply hz optimization",
142    initializers = {
143        base = initializeexpansion,
144        node = initializeexpansion,
145    }
146}
147
148registerotffeature(specification)
149registerafmfeature(specification)
150
151-- normalizer (generic only)
152
153if not otf.features.normalize then
154
155    otf.features.normalize = function(t)
156        if t.rand then
157            t.rand = "random"
158        end
159        return t
160    end
161
162end
163
164-- bonus
165
166function fonts.helpers.nametoslot(name)
167    local t = type(name)
168    if t == "string" then
169        local tfmdata = fonts.hashes.identifiers[currentfont()]
170        local shared  = tfmdata and tfmdata.shared
171        local fntdata = shared and shared.rawdata
172        return fntdata and fntdata.resources.unicodes[name]
173    elseif t == "number" then
174        return n
175    end
176end
177
178-- \font\test=file:somefont:reencode=mymessup
179--
180--  fonts.encodings.reencodings.mymessup = {
181--      [109] = 110, -- m
182--      [110] = 109, -- n
183--  }
184
185-- reencoding (generic only)
186
187fonts.encodings             = fonts.encodings or { }
188local reencodings           = { }
189fonts.encodings.reencodings = reencodings
190
191local function specialreencode(tfmdata,value)
192    -- we forget about kerns as we assume symbols and we
193    -- could issue a message if ther are kerns but it's
194    -- a hack anyway so we odn't care too much here
195    local encoding = value and reencodings[value]
196    if encoding then
197        local temp = { }
198        local char = tfmdata.characters
199        for k, v in next, encoding do
200            temp[k] = char[v]
201        end
202        for k, v in next, temp do
203            char[k] = temp[k]
204        end
205        -- if we use the font otherwise luatex gets confused so
206        -- we return an additional hash component for fullname
207        return string.format("reencoded:%s",value)
208    end
209end
210
211local function initialize(tfmdata,value)
212    tfmdata.postprocessors = tfmdata.postprocessors or { }
213    table.insert(tfmdata.postprocessors,
214        function(tfmdata)
215            return specialreencode(tfmdata,value)
216        end
217    )
218end
219
220registerotffeature {
221    name         = "reencode",
222    description  = "reencode characters",
223    manipulators = {
224        base = initialize,
225        node = initialize,
226    }
227}
228
229-- math stuff (generic only)
230
231local function initialize(tfmdata,key,value)
232    if value then
233        tfmdata.mathparameters = nil
234    end
235end
236
237registerotffeature {
238    name         = "ignoremathconstants",
239    description  = "ignore math constants table",
240    initializers = {
241        base = initialize,
242        node = initialize,
243    }
244}
245