font-imp-tracing.lmt /size: 14 Kb    last modification: 2024-01-16 09:02
1if not modules then modules = { } end modules ['font-imp-tracing'] = {
2    version   = 1.001,
3    comment   = "companion to font-ini.mkiv and hand-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
9local abs = math.abs
10
11local next, type = next, type
12local concat = table.concat
13local formatters = string.formatters
14
15local fonts              = fonts
16
17local handlers           = fonts.handlers
18local registerotffeature = handlers.otf.features.register
19local registerafmfeature = handlers.afm.features.register
20
21local settings_to_array  = utilities.parsers.settings_to_array
22local setmetatableindex  = table.setmetatableindex
23
24local helpers            = fonts.helpers
25local appendcommandtable = helpers.appendcommandtable
26local prependcommands    = helpers.prependcommands
27local charcommand        = helpers.commands.char
28
29local variables          = interfaces.variables
30
31local v_background       = variables.background
32local v_frame            = variables.frame
33local v_empty            = variables.empty
34local v_none             = variables.none
35
36-- d:width d:height d:depth d:rulethickness b:outline b:advance b:baseline s:color
37
38-- local function initialize(tfmdata,key,value)
39--     if value then
40--         local vfspecials  = fonts.helpers.vfspecials
41--         local vfcommands  = fonts.helpers.commands
42--         local backgrounds = vfspecials.backgrounds
43--         local outlines    = vfspecials.outlines
44--         local characters  = tfmdata.characters
45--         local rulecache   = backgrounds
46--         local showchar    = true
47--         local color       = "palegray"
48--         if type(value) == "string" then
49--             value = settings_to_array(value)
50--             for i=1,#value do
51--                 local v = value[i]
52--                 if v == v_frame then
53--                     rulecache = outlines
54--                 elseif v == v_background then
55--                     rulecache = backgrounds
56--                 elseif v == v_empty then
57--                     showchar = false
58--                 elseif v == v_none then
59--                     color = nil
60--                 else
61--                     color = v
62--                 end
63--             end
64--         end
65--         local gray  = color and { "startcolor", color } or nil
66--         local black = gray  and { "stopcolor" }         or nil
67--         for unicode, character in next, characters do
68--             local width  = character.width  or 0
69--             local height = character.height or 0
70--             local depth  = character.depth  or 0
71--             local rule   = rulecache[height][depth][width]
72--             if showchar then
73--                 local commands = character.commands
74--                 if commands then
75--                     if gray then
76--                         character.commands = prependcommands (
77--                             commands, gray, rule, black
78--                         )
79--                     else
80--                         character.commands = prependcommands (
81--                             commands, rule
82--                         )
83--                     end
84--                 else
85--                     local char = charcommand[unicode]
86--                     if gray then
87--                         character.commands = {
88--                             gray, rule, black, char
89--                         }
90--                      else
91--                         character.commands = {
92--                             rule, char
93--                         }
94--                     end
95--                 end
96--             else
97--                 if gray then
98--                     character.commands = {
99--                         gray, rule, black
100--                     }
101--                 else
102--                     character.commands = {
103--                         rule
104--                     }
105--                 end
106--             end
107--         end
108--     end
109-- end
110
111local function initialize(tfmdata,key,value)
112    if value then
113        local vfspecials  = fonts.helpers.vfspecials
114        local vfcommands  = fonts.helpers.commands
115     -- local backgrounds = vfspecials.backgrounds
116     -- local outlines    = vfspecials.outlines
117        local characters  = tfmdata.characters
118        local rule        = { "frame", true, true, true, false, false, false, false, "palegray" }
119        local showchar    = true
120        if type(value) == "string" then
121            value = settings_to_array(value)
122            for i=1,#value do
123                local v = value[i]
124                if v == v_frame then
125                    rule[6] = true
126                elseif v == v_background then
127                    rule[6] = false
128                elseif v == v_empty then
129                    showchar = false
130                elseif v == v_none then
131                    rule[9] = false
132                else
133                    local thickness = string.todimen(v)
134                    if thickness and thickness > 0 then
135                        rule[5] = thickness
136                    else
137                        rule[9] = v
138                    end
139                end
140            end
141        end
142        if not showchar then
143            rule = { rule }
144        end
145        for unicode, character in next, characters do
146            if characters == 32 then
147                -- maybe skip all spacing
148            elseif showchar then
149                local commands = character.commands
150                if commands then
151                    character.commands = prependcommands ( commands, rule )
152                else
153                    character.commands = { rule, charcommand[unicode] }
154                end
155            else
156                character.commands = rule
157            end
158        end
159    end
160end
161
162local specification = {
163    name        = "boundingbox",
164    description = "show boundingbox",
165    manipulators = {
166        base = initialize,
167        node = initialize,
168    }
169}
170
171registerotffeature(specification)
172registerafmfeature(specification)
173
174local function initialize(tfmdata,key,value)
175    if value then
176        local rawdata       = tfmdata.shared.rawdata
177        local rawresources  = rawdata and rawdata.resources
178        local mathconstants = rawresources.mathconstants
179        if mathconstants then
180            local vfspecials  = fonts.helpers.vfspecials
181            local vfcommands  = fonts.helpers.commands
182            local backgrounds = vfspecials.backgrounds
183         -- local outlines    = vfspecials.outlines
184            local characters  = tfmdata.characters
185            local rulecache   = backgrounds
186            local push        = vfcommands.push
187            local pop         = vfcommands.pop
188            local black       = { "stopcolor" }
189            local itcolor     = { "startcolor", "trace:0" } -- s / dd (transparent)
190            local brcolor     = { "startcolor", "trace:1" } -- r / dr
191            local trcolor     = { "startcolor", "trace:2" } -- g / dg
192            local blcolor     = { "startcolor", "trace:3" } -- b / db
193            local tlcolor     = { "startcolor", "trace:4" } -- y / dy
194            for unicode, character in next, characters do
195                local mathkerns = character.mathkerns
196                local italic    = character.vitalic or character.italic
197
198if italic ~= italic then
199    -- 8427 in pagella suddenly gets a "nan" assigned ... can this be a lua bug
200    -- test file : staircase-001.tex
201    italic = 0
202end
203
204                if mathkerns or (italic and italic ~= 0) then
205                    local width  = character.width  or 0
206                    local height = character.height or 0
207                    local depth  = character.depth  or 0
208                    local list   = { }
209                    local count  = 0
210                    if italic and italic ~= 0 then
211                        count = count + 1 list[count] = itcolor
212                        count = count + 1 list[count] = push
213                        count = count + 1 list[count] = { "offset", width + (italic < 0 and -italic or 0), 0 }
214                        count = count + 1 list[count] = rulecache[height][depth][italic < 0 and -italic or italic]
215                        count = count + 1 list[count] = pop
216                        count = count + 1 list[count] = black
217                    end
218                    if mathkerns then
219                        local br = mathkerns.bottomright
220                        local tr = mathkerns.topright
221                        local bl = mathkerns.bottomleft
222                        local tl = mathkerns.topleft
223                        if br then
224                            local done = false
225                            for i=1,#br do
226                                local l = br[i]
227                                local h = l.height or 0
228                                local k = l.kern or 0
229                                if k ~= 0 then
230                                    if h == 0 then
231                                        h = height + depth -- todo max
232                                    end
233                                    if not done then
234                                        count = count + 1 list[count] = brcolor
235                                        done  = true
236                                    end
237                                    count = count + 1 list[count] = push
238                                    count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), - depth }
239                                    count = count + 1 list[count] = rulecache[h][0][k < 0 and -k or k]
240                                    count = count + 1 list[count] = pop
241                                end
242                            end
243                            if done then
244                                count = count + 1 list[count] = black
245                            end
246                        end
247                        if tr then
248                            local done = false
249                            for i=1,#tr do
250                                local l = tr[i]
251                                local h = l.height or 0
252                                local k = l.kern or 0
253                                if k ~= 0 then
254                                    if h == 0 then
255                                        h = height + depth -- todo max
256                                    end
257                                    if not done then
258                                        count = count + 1 list[count] = trcolor
259                                        done  = true
260                                    end
261                                    count = count + 1 list[count] = push
262                                    count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), height - h }
263                                    count = count + 1 list[count] = rulecache[h][0][k < 0 and k or k]
264                                    count = count + 1 list[count] = pop
265                                end
266                            end
267                            if done then
268                                count = count + 1 list[count] = black
269                            end
270                        end
271                        if bl then
272                            local done = false
273                            for i=1,#bl do
274                                local l = bl[i]
275                                local h = l.height or 0
276                                local k = l.kern or 0
277                                if k ~= 0 then
278                                    if h == 0 then
279                                        h = height + depth -- todo max
280                                    end
281                                    if not done then
282                                        count = count + 1 list[count] = blcolor
283                                        done  = true
284                                    end
285                                    count = count + 1 list[count] = push
286                                    count = count + 1 list[count] = { "offset", (k < 0 and k or 0), -depth }
287                                    count = count + 1 list[count] = rulecache[h][0][abs(k)]
288                                    count = count + 1 list[count] = pop
289                                end
290                            end
291                            if done then
292                                count = count + 1 list[count] = black
293                            end
294                        end
295                        if tl then
296                            local done = false
297                            for i=1,#tl do
298                                local l = tl[i]
299                                local h = l.height or 0
300                                local k = l.kern or 0
301                                if k ~= 0 then
302                                    if h == 0 then
303                                        h = height + depth -- todo max
304                                    end
305                                    if not done then
306                                        count = count + 1 list[count] = tlcolor
307                                        done  = true
308                                    end
309                                    count = count + 1 list[count] = push
310                                    count = count + 1 list[count] = { "offset", (k < 0 and k or 0), height - h }
311                                    count = count + 1 list[count] = rulecache[h][0][abs(k)]
312                                    count = count + 1 list[count] = pop
313                                end
314                            end
315                            if done then
316                                count = count + 1 list[count] = black
317                            end
318                        end
319                    end
320                    if count > 0 then
321                        local commands = character.commands
322                        if commands then
323                            character.commands = appendcommandtable(commands,list)
324                        else
325                            list[#list+1] = charcommand[unicode]
326                            character.commands = list
327                        end
328                    end
329                end
330            end
331        end
332    end
333end
334
335local specification = {
336    name         = "staircase",
337    description  = "show staircase kerns",
338--  position     = 1,
339    manipulators = {
340        base = initialize,
341        node = initialize,
342    }
343}
344
345registerotffeature(specification)
346registerafmfeature(specification)
347