1if not modules then modules = { } end modules ['meta-blb'] = {
2 version = 1.001,
3 comment = "companion to mlib-ctx.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
9
10
11
12local tonumber = tonumber
13
14local setmetatableindex = table.setmetatableindex
15local insert, remove = table.insert, table.remove
16local formatters = string.formatters
17
18local topoints = number.topoints
19local mpprint = mp.print
20local mpinteger = mp.integer
21local mppoints = mp.points
22local mptriplet = mp.triplet
23local mptripletpoints = mp.tripletpoints
24
25local nuts = nodes.nuts
26local hpack = nuts.hpack
27local setbox = nuts.setbox
28local getwhd = nuts.getwhd
29local getwidth = nuts.getwidth
30local toutf = nuts.toutf
31
32local trace = false
33local report = logs.reporter("metapost","blobs")
34
35trackers.register("metapost.blobs", function(v) trace = v end)
36
37local allblobs = { }
38
39local function newcategory(t,k)
40 if trace then
41 report("new category %a",k)
42 end
43 local v = {
44 name = k,
45 text = "",
46 blobs = { },
47 }
48 t[k] = v
49 return v
50end
51
52local texblobs = setmetatableindex(newcategory)
53
54local function blob_raw_reset(category)
55
56 if category then
57 if trace then
58 report("reset category %a",category)
59 end
60 texblobs[category] = nil
61 else
62 if trace then
63 report("reset all")
64 end
65 texblobs = setmetatableindex(newcategory)
66 end
67end
68
69local function blob_raw_dimensions(i)
70 local blob = allblobs[i]
71 if blob then
72 return getwhd(blob)
73 else
74 return 0, 0, 0
75 end
76end
77
78local function blob_raw_content(i)
79 return allblobs[i]
80end
81
82local function blob_raw_toutf(i)
83 return toutf(allblobs[i])
84end
85
86local function blob_raw_wipe(i)
87 allblobs[i] = false
88end
89
90mp.mf_blob_raw_dimensions = blob_raw_dimensions
91mp.mf_blob_raw_content = blob_raw_content
92mp.mf_blob_raw_reset = blob_raw_reset
93mp.mf_blob_raw_wipe = blob_raw_wipe
94mp.mf_blob_raw_toutf = blob_raw_toutf
95
96function mp.mf_blob_new(category,text)
97 if trace then
98 report("category %a, text %a",category,text)
99 end
100 texblobs[category].text = text
101end
102
103function mp.mf_blob_add(category,blob)
104 local tb = texblobs[category].blobs
105 local tn = #allblobs + 1
106 blob = hpack(blob)
107 allblobs[tn] = blob
108 tb[#tb+1] = tn
109 if trace then
110 report("category %a, blob %a set, content %a",category,tn,blob_raw_toutf(tn))
111 end
112end
113
114function mp.mf_blob_width(category,i)
115 local index = texblobs[category].blobs[i]
116 local blob = allblobs[index]
117 if blob then
118 mppoints(getwidth(blob) or 0)
119 else
120 mpinteger(0)
121 end
122end
123
124function mp.mf_blob_size(category,i)
125 mpprint(#texblobs[category].blobs or 0)
126end
127
128function mp.mf_blob_index(category,i)
129 mpprint(texblobs[category].blobs[i] or 0)
130end
131
132function mp.mf_blob_dimensions(category,i)
133 local index = texblobs[category].blobs[i]
134 local blob = allblobs[index]
135 if blob then
136 mptripletpoints(getwhd(blob))
137 else
138 mptriplet(0,0,0)
139 end
140end
141
142local sxsy = metapost.sxsy
143local cm = metapost.cm
144
145local f_f = formatters["%.6N"]
146
147local function injectblob(object,blob)
148 local sx, rx, ry, sy, tx, ty = cm(object)
149 local wd, ht, dp = blob_raw_dimensions(blob)
150 if wd then
151 object.path = false
152 object.color = false
153 object.grouped = true
154 object.istext = true
155 return function()
156 if trace then
157 report("injecting blob %a, width %p, heigth %p, depth %p, text %a",blob,wd,ht,dp,blob_raw_toutf(blob))
158 end
159 context.MPLIBgetblobscaledcm(blob,
160 f_f(sx), f_f(rx), f_f(ry),
161 f_f(sy), f_f(tx), f_f(ty),
162 sxsy(wd,ht,dp))
163 end
164 end
165end
166
167
168
169local function getblob(box,blob)
170 setbox(box,blob_raw_content(blob))
171 blob_raw_wipe(blob)
172end
173
174interfaces.implement {
175 name = "mpgetblob",
176 actions = getblob,
177 arguments = { "integer", "integer" },
178}
179
180
181
182
183local function reset()
184 blob_raw_reset()
185end
186
187local function process(object,prescript,before,after)
188
189 local tb_blob = tonumber(prescript.tb_blob)
190 if tb_blob then
191 before[#before+1] = injectblob(object,tb_blob)
192 end
193
194end
195
196metapost.installplugin {
197 name = "texblob",
198 reset = reset,
199 process = process,
200}
201
202
203
204
205local nodecodes = nodes.nodecodes
206local kerncodes = nodes.kerncodes
207
208local glue_code = nodecodes.glue
209local kern_code = nodecodes.kern
210
211local fontkern_code = kerncodes.fontkern
212local italickern_code = kerncodes.italickern
213
214local a_fontkern = attributes.private("fontkern")
215
216local nuts = nodes.nuts
217local takebox = nuts.takebox
218local getlist = nuts.getlist
219local getid = nuts.getid
220local getsubtype = nuts.getsubtype
221local setlink = nuts.setlink
222local setlist = nuts.setlist
223local getnext = nuts.getnext
224local flatten_list = nuts.flattendiscretionaries
225local remove_node = nuts.remove
226local flushnode = nuts.flush
227
228local addblob = mp.mf_blob_add
229local newblob = mp.mf_blob_new
230
231local visible_codes = {
232 [nodecodes.glyph] = true,
233 [nodecodes.glue] = true,
234 [nodecodes.hlist] = true,
235 [nodecodes.vlist] = true,
236 [nodecodes.rule] = true,
237}
238
239local function initialize(category,box)
240 local wrap = takebox(box)
241 if wrap then
242 local head = getlist(wrap)
243 local tail = nil
244 local temp = nil
245 if head then
246 local n = { }
247 local s = 0
248 head = flatten_list(head)
249 local current = head
250 while current do
251 local id = getid(current)
252 if visible_codes[id] then
253 head, current, tail = remove_node(head,current)
254 s = s + 1
255 n[s] = tail
256 elseif id == kern_code then
257 local subtype = getsubtype(current)
258 if subtype == fontkern_code or subtype == italickern_code then
259 head, current, temp = remove_node(head,current)
260 setlink(tail,temp)
261 else
262 head, current, temp = remove_node(head,current)
263 s = s + 1
264 n[s] = temp
265 end
266 elseif id == glue_code then
267 head, current, temp = remove_node(head,current)
268 s = s + 1
269 n[s] = temp
270 else
271 current = getnext(current)
272 end
273 end
274 for i=1,s do
275 n[i] = addblob(category,n[i])
276 end
277 setlist(wrap,head)
278 end
279 flushnode(wrap)
280 end
281end
282
283interfaces.implement {
284 name = "MPLIBconvertfollowtext",
285 arguments = { "integer","integer" },
286 actions = initialize,
287}
288
289local mp_category = 0
290local mp_str = ""
291
292function mp.mf_inject_blob(category,str)
293 newblob(category,str)
294 mp_category = category
295 mp_str = str
296 tex.runlocal("mpblobtext")
297end
298
299interfaces.implement {
300 name = "mpblobtext",
301 actions = function()
302 context.MPLIBfollowtext(mp_category,mp_str)
303 end
304}
305
306local process = function(object,prescript,before,after)
307 if prescript.ft_category then
308 object.path = false
309 object.color = false
310 object.grouped = true
311 object.istext = true
312 end
313end
314
315metapost.installplugin {
316 name = "followtext",
317 process = process,
318}
319 |