font-imp-dimensions.lua /size: 4929 b    last modification: 2024-01-16 09:02
1if not modules then modules = { } end modules ['font-imp-dimensions'] = {
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
9if not context then return end
10
11local next, type, tonumber = next, type, tonumber
12
13local fonts              = fonts
14local utilities          = utilities
15
16local helpers            = fonts.helpers
17local prependcommands    = helpers.prependcommands
18local charcommand        = helpers.commands.char
19local rightcommand       = helpers.commands.right
20
21local handlers           = fonts.handlers
22local otf                = handlers.otf
23local afm                = handlers.afm
24
25local registerotffeature = otf.features.register
26local registerafmfeature = afm.features.register
27
28local settings_to_array  = utilities.parsers.settings_to_array
29local gettexdimen        = tex.getdimen
30
31-- For Wolfgang Schuster:
32--
33-- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}]
34-- \definedfont[file:kozminpr6nregular*thisway]
35
36local function initialize(tfmdata,key,value)
37    if type(value) == "string" and value ~= "" then
38        local characters = tfmdata.characters
39        local parameters = tfmdata.parameters
40        local emwidth    = parameters.quad
41        local exheight   = parameters.xheight
42        local newwidth   = false
43        local newheight  = false
44        local newdepth   = false
45        local newshift   = false
46        if value == "strut" then
47            newheight = gettexdimen("strutht")
48            newdepth  = gettexdimen("strutdp")
49        elseif value == "mono" then
50            newwidth  = emwidth
51        elseif value == "halfmono" then
52            newwidth  = emwidth / 2
53        else
54            -- there are fonts out there with no x_height ...
55            local spec = settings_to_array(value)
56            newwidth  = spec[1]
57            newheight = spec[2]
58            newdepth  = spec[3]
59            newshift  = spec[4]
60            local quad      = parameters.quad      or 0
61            local ascender  = parameters.ascender  or 0
62            local descender = parameters.descender or 0
63            if newwidth  == "max" then
64                newwidth = quad
65            else
66                newwidth = tonumber(newwidth)
67                if newwidth then
68                    newwidth = newwidth * emwidth
69                end
70            end
71            if newheight == "max" then
72                newheight = ascender
73            else
74                newheight = tonumber(newheight)
75                if newheight then
76                    newheight = newheight * exheight
77                end
78            end
79            if newdepth == "max" then
80                newdepth = descender
81            else
82                newdepth = tonumber(newdepth)
83                if newdepth then
84                    newdepth  = newdepth  * exheight
85                end
86            end
87            if parameters.x_heigth == 0 then
88                -- maybe a fourth parameter
89                parameters.x_heigth = (ascender + descender) / 2
90            end
91        end
92        -- todo: hshift too
93        if newwidth or newheight or newdepth then
94            for unicode, character in next, characters do
95                local oldwidth  = character.width
96                local oldheight = character.height
97                local olddepth  = character.depth
98                local width  = newwidth  or oldwidth  or 0
99                local height = newheight or oldheight or 0
100                local depth  = newdepth  or olddepth  or 0
101                if oldwidth ~= width or oldheight ~= height or olddepth ~= depth then
102                    character.width  = width
103                    character.height = height
104                    character.depth  = depth
105                    if oldwidth ~= width then
106                        -- todo: xoffset
107                        local commands = character.commands
108                        local hshift   = rightcommand[newshift or ((width - oldwidth) / 2)]
109                        if commands then
110                            character.commands = prependcommands (
111                                commands,
112                                hshift
113                            )
114                        else
115                            character.commands = {
116                                hshift,
117                                charcommand[unicode],
118                            }
119                        end
120                    end
121                end
122            end
123        end
124    end
125end
126
127local specification = {
128    name        = "dimensions",
129    description = "force dimensions",
130    manipulators = {
131        base = initialize,
132        node = initialize,
133    }
134}
135
136registerotffeature(specification)
137registerafmfeature(specification)
138