font-tex.lmt /size: 5880 b    last modification: 2021-10-28 13:51
1if not modules then modules = { } end modules ['font-mpf'] = {
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
9local formatters        = string.formatters
10local sortedhash        = table.sortedhash
11
12local addcharacters     = fonts.constructors.addcharacters
13local fontdata          = fonts.hashes.identifiers
14
15local otf               = fonts.handlers.otf
16local otfregister       = otf.features.register
17
18----- getshapes         = fonts.dropins.getshapes
19
20local register          = fonts.collections.register
21local checkenabled      = fonts.collections.checkenabled
22local newprivateslot    = fonts.helpers.newprivateslot
23
24local currentfont       = font.current
25
26-- hm, seems to gobble the first \char
27
28local makesetups = formatters["box:%s:%S"]
29
30local function makeglyphbox(char,spec)
31    token.expand_macro("makeglyphbox",true,spec.setups or tostring(char))
32    local b = tex.takebox("glyphbox")
33    spec.code = {
34        width  = b.width,
35        height = b.height,
36        depth  = b.depth,
37        objnum = tex.boxresources.save(b,nil,nil,true),
38    }
39end
40
41local function setboxglyphs(category,fontid,unicode,specification)
42    local box = specification.code
43    if unicode and box then
44        local tfmdata    = fontdata[fontid]
45        local characters = tfmdata.characters
46        local newdata    = {
47            width   = box.width  or 0,
48            height  = box.height or 0,
49            depth   = box.depth  or 0,
50            unicode = unicode,
51        }
52        -- pass dimensions to lua
53        characters[unicode] = newdata
54        -- this also adapts newdata (add commands)
55        fonts.dropins.swapone("box",tfmdata,specification,unicode)
56        -- pass dimensions to tex
57        addcharacters(fontid, { characters = { [unicode] = newdata } })
58        return fontid, unicode
59    else
60        logs.report("box glyph", "invalid glyph box for %C",unicode)
61    end
62end
63
64local function setboxglyph(specification)
65    if specification then
66        local name    = specification.name
67        local unicode = specification.unicode
68        local font    = currentfont()
69        if not unicode and name then
70            unicode = newprivateslot(name)
71            specification.unicode = unicode
72        end
73        if unicode then
74            if not specification.setups then
75                specification.setups = name
76            end
77            -- we can actually delay font if needed
78            register(font,unicode,function(font,private)
79                makeglyphbox(unicode,specification)
80                return setboxglyphs(category,font,unicode,specification)
81            end)
82            checkenabled()
83        end
84    end
85end
86
87function fonts.helpers.setboxdirectly(font,unicode,box) -- hash based on wd/ht/dp
88    if box then
89        local tfmdata      = fontdata[font]
90        local glyphboxes   = (tfmdata.glyphboxes or 0) + 1
91        tfmdata.glyphboxes = glyphboxes
92        local private      = newprivateslot(formatters["BG:%05X"](glyphboxes))
93        local newdata      = {
94            width   = box.width  or 0,
95            height  = box.height or 0,
96            depth   = box.depth  or 0,
97            unicode = unicode,
98            objnum  = tex.boxresources.save(box,nil,nil,true),
99        }
100        local specification = {
101            code = newdata
102        }
103        tfmdata.characters[private] = newdata
104        addcharacters(font, { characters = { [private] = newdata } })
105        fonts.dropins.swapone("box",tfmdata,specification,private)
106        checkenabled()
107        return private
108    end
109end
110
111local boxes = table.setmetatableindex("table")
112
113function fonts.helpers.registerglyphbox(specification)
114    local category = specification.category
115    local whatever = specification.unicode or specification.name
116    if category and whatever then
117        boxes[category][whatever] = { action = makeglyphbox } -- always
118    end
119end
120
121local function initializebox(tfmdata,kind,value)
122    local boxes = boxes[value]
123    if value then
124        local font = tfmdata.properties.id
125        -- just preregister the list
126        for char, spec in sortedhash(boxes) do
127            spec.setups = makesetups(value,char)
128            if type(char) == "string" then
129                char = newprivateslot(name)
130            end
131            -- check if spec.code
132            register(font,char,function(font,char)
133                local action = spec.action
134                if type(action) == "function" then
135                    action(char,spec)
136                end
137                return setboxglyphs(value,font,char,spec)
138            end)
139        end
140        checkenabled()
141    end
142end
143
144fonts.helpers.setboxglyphs = setboxglyphs
145fonts.helpers.setboxglyph  = setboxglyph
146
147interfaces.implement {
148    name      = "registerboxglyph", -- combine with next one
149    public    = true,
150    protected = true,
151    actions   = fonts.helpers.registerglyphbox,
152    arguments = { {
153        { "category" },
154        { "unicode", "integer" },
155        { "name" },
156    } },
157}
158
159interfaces.implement {
160    name      = "setboxglyph",
161    public    = true,
162    protected = true,
163    actions   = setboxglyph,
164    arguments = { {
165        { "category" },
166        { "unicode", "integer" },
167        { "name" },
168        { "*" }
169    } },
170}
171
172fonts.handlers.otf.features.register {
173    name         = "box",
174    description  = "box glyphs",
175    manipulators = {
176        base = initializebox,
177        node = initializebox,
178    }
179}
180
181-- fonts.helpers.registerboxglyph { category = "demo", unicode = 103 }
182-- fonts.helpers.registerboxglyph { category = "demo", unicode = 104 }
183-- fonts.helpers.registerboxglyph { category = "demo", unicode = 105 }
184-- fonts.helpers.registerboxglyph { category = "demo", unicode = 106 }
185