summaryrefslogtreecommitdiff
path: root/tex/context/base/font-enh.lua
blob: fc70c04c5661de0bcaf715682e203fff6c23f552 (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
if not modules then modules = { } end modules ['font-enh'] = {
    version   = 1.001,
    comment   = "companion to font-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local next, match = next, string.match

local trace_defining = false  trackers.register("fonts.defining", function(v) trace_defining = v end)

-- tfmdata has also fast access to indices and unicodes
-- to be checked: otf -> tfm -> tfmscaled
--
-- watch out: no negative depths and negative eights permitted in regular fonts

--[[ldx--
<p>Here we only implement a few helper functions.</p>
--ldx]]--

local tfm = fonts.tfm

--[[ldx--
<p>The next function encapsulates the standard <l n='tfm'/> loader as
supplied by <l n='luatex'/>.</p>
--ldx]]--

-- auto complete font with missing composed characters

table.insert(fonts.manipulators,"compose")

function fonts.initializers.common.compose(tfmdata,value)
    if value then
        fonts.vf.aux.compose_characters(tfmdata)
    end
end

-- tfm features, experimental

tfm.features         = tfm.features         or { }
tfm.features.list    = tfm.features.list    or { }
tfm.features.default = tfm.features.default or { }

function tfm.enhance(tfmdata,specification)
    -- we don't really share tfm data because we always reload
    -- but this is more in sycn with afm and such
    local features = (specification.features and specification.features.normal ) or { }
    tfmdata.shared = tfmdata.shared or { }
    tfmdata.shared.features = features
    --  tfmdata.shared.tfmdata = tfmdata -- circular
    tfmdata.filename = specification.name
    if not features.encoding then
        local name, size = specification.name, specification.size
        local encoding, filename = match(name,"^(.-)%-(.*)$") -- context: encoding-name.*
        if filename and encoding and fonts.enc.known[encoding] then
            features.encoding = encoding
        end
    end
    tfm.set_features(tfmdata)
end

function tfm.set_features(tfmdata)
    -- todo: no local functions
    local shared = tfmdata.shared
--  local tfmdata = shared.tfmdata
    local features = shared.features
    if features and next(features) then
        local mode = tfmdata.mode or fonts.mode
        local fi = fonts.initializers[mode]
        if fi and fi.tfm then
            local function initialize(list) -- using tex lig and kerning
                if list then
                    for i=1,#list do
                        local f = list[i]
                        local value = features[f]
                        if value and fi.tfm[f] then -- brr
                            if tfm.trace_features then
                                logs.report("define font","initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.name or 'unknown')
                            end
                            fi.tfm[f](tfmdata,value)
                            mode = tfmdata.mode or fonts.mode
                            fi = fonts.initializers[mode]
                        end
                    end
                end
            end
            initialize(fonts.triggers)
            initialize(tfm.features.list)
            initialize(fonts.manipulators)
        end
        local fm = fonts.methods[mode]
        if fm and fm.tfm then
            local function register(list) -- node manipulations
                if list then
                    for i=1,#list do
                        local f = list[i]
                        if features[f] and fm.tfm[f] then -- brr
                            if not shared.processors then -- maybe also predefine
                                shared.processors = { fm.tfm[f] }
                            else
                                shared.processors[#shared.processors+1] = fm.tfm[f]
                            end
                        end
                    end
                end
            end
            register(tfm.features.list)
        end
    end
end

function tfm.features.register(name,default)
    tfm.features.list[#tfm.features.list+1] = name
    tfm.features.default[name] = default
end

function tfm.reencode(tfmdata,encoding)
    if encoding and fonts.enc.known[encoding] then
        local data = fonts.enc.load(encoding)
        if data then
            local characters, original, vector = tfmdata.characters, { }, data.vector
            tfmdata.encoding = encoding -- not needed
            for k, v in next, characters do
                v.name, v.index, original[k] = vector[k], k, v
            end
            for k,v in next, data.unicodes do
                if k ~= v then
                    if trace_defining then
                        logs.report("define font","reencoding U+%04X to U+%04X",k,v)
                    end
                    characters[k] = original[v]
                end
            end
        end
    end
end

tfm.features.register('reencode')

fonts.initializers.base.tfm.reencode = tfm.reencode
fonts.initializers.node.tfm.reencode = tfm.reencode

fonts.enc            = fonts.enc            or { }
fonts.enc.remappings = fonts.enc.remappings or { }

function tfm.remap(tfmdata,remapping)
    local vector = remapping and fonts.enc.remappings[remapping]
    if vector then
        local characters, original = tfmdata.characters, { }
        for k, v in next, characters do
            original[k], characters[k] = v, nil
        end
        for k,v in next, vector do
            if k ~= v then
                if trace_defining then
                    logs.report("define font","remapping U+%04X to U+%04X",k,v)
                end
                local c = original[k]
                characters[v] = c
                c.index = k
            end
        end
        tfmdata.encodingbytes = 2
        tfmdata.format = 'type1'
    end
end

tfm.features.register('remap')

fonts.initializers.base.tfm.remap = tfm.remap
fonts.initializers.node.tfm.remap = tfm.remap

--~ obsolete
--~
--~ function tfm.enhance(tfmdata,specification)
--~     local name, size = specification.name, specification.size
--~     local encoding, filename = match(name,"^(.-)%-(.*)$") -- context: encoding-name.*
--~     if filename and encoding and fonts.enc.known[encoding] then
--~         local data = fonts.enc.load(encoding)
--~         if data then
--~             local characters = tfmdata.characters
--~             tfmdata.encoding = encoding
--~             local vector = data.vector
--~             local original = { }
--~             for k, v in next, characters do
--~                 v.name = vector[k]
--~                 v.index = k
--~                 original[k] = v
--~             end
--~             for k,v in next, data.unicodes do
--~                 if k ~= v then
--~                     if trace_defining then
--~                         logs.report("define font","mapping %s onto %s",k,v)
--~                     end
--~                     characters[k] = original[v]
--~                 end
--~             end
--~         end
--~     end
--~ end