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
19
20local register = fonts.collections.register
21local checkenabled = fonts.collections.checkenabled
22local newprivateslot = fonts.helpers.newprivateslot
23
24local currentfont = font.current
25
26
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
53 characters[unicode] = newdata
54
55 fonts.dropins.swapone("box",tfmdata,specification,unicode)
56
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
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)
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 }
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
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
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",
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
182
183
184
185 |