1if not modules then modules = { } end modules [ ' math-vfu ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to math-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
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25local type , next , tonumber = type , next , tonumber
26local max = math . max
27local fastcopy = table . copy
28
29local fonts , nodes , mathematics = fonts , nodes , mathematics
30
31local trace_virtual = false trackers . register ( " math.virtual " , function ( v ) trace_virtual = v end )
32local trace_timings = false trackers . register ( " math.timings " , function ( v ) trace_timings = v end )
33
34local add_optional = false directives . register ( " math.virtual.optional " , function ( v ) add_optional = v end )
35
36local report_virtual = logs . reporter ( " fonts " , " virtual math " )
37
38local allocate = utilities . storage . allocate
39local setmetatableindex = table . setmetatableindex
40local formatters = string . formatters
41
42local chardata = characters . data
43
44local mathencodings = allocate ( )
45fonts . encodings . math = mathencodings
46local vfmath = allocate ( )
47fonts . handlers . vf . math = vfmath
48
49local helpers = fonts . helpers
50local vfcommands = helpers . commands
51local rightcommand = vfcommands . right
52local leftcommand = vfcommands . left
53local downcommand = vfcommands . down
54local upcommand = vfcommands . up
55local push = vfcommands . push
56local pop = vfcommands . pop
57
58local shared = { }
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91local function brace ( main , characters , id , size , unicode , first , rule , left , right , rule , last )
92 if not characters [ unicode ] then
93 characters [ unicode ] = {
94 horiz_variants = {
95 { extender = 0 , glyph = first } ,
96 { extender = 1 , glyph = rule } ,
97 { extender = 0 , glyph = left } ,
98 { extender = 0 , glyph = right } ,
99 { extender = 1 , glyph = rule } ,
100 { extender = 0 , glyph = last } ,
101 }
102 }
103 end
104end
105
106local function extension ( main , characters , id , size , unicode , first , middle , last )
107 local chr = characters [ unicode ]
108 if not chr then
109 return
110 end
111 local fw = characters [ first ]
112 if not fw then
113 return
114 end
115 local mw = characters [ middle ]
116 if not mw then
117 return
118 end
119 local lw = characters [ last ]
120 if not lw then
121 return
122 end
123 fw = fw . width
124 mw = mw . width
125 lw = lw . width
126 if fw = = 0 then
127 fw = 1
128 end
129 if lw = = 0 then
130 lw = 1
131 end
132 chr . horiz_variants = {
133 { extender = 0 , glyph = first , [ " end " ] = fw / 2 , start = 0 , advance = fw } ,
134 { extender = 1 , glyph = middle , [ " end " ] = mw / 2 , start = mw / 2 , advance = mw } ,
135 { extender = 0 , glyph = last , [ " end " ] = 0 , start = lw / 2 , advance = lw } ,
136 }
137end
138
139local function parent ( main , characters , id , size , unicode , first , rule , last )
140 if not characters [ unicode ] then
141 characters [ unicode ] = {
142 horiz_variants = {
143 { extender = 0 , glyph = first } ,
144 { extender = 1 , glyph = rule } ,
145 { extender = 0 , glyph = last } ,
146 }
147 }
148 end
149end
150
151local step = 0 . 2
152
153local function make ( main , characters , id , size , n , m )
154 local old = 0xFF000 + n
155 local c = characters [ old ]
156 if c then
157 local upslot = 0xFF100 + n
158 local dnslot = 0xFF200 + n
159 local uprule = 0xFF300 + m
160 local dnrule = 0xFF400 + m
161 local xu = main . parameters . x_height + 0 . 3 * size
162 local xd = 0 . 3 * size
163 local w = c . width or 0
164 local h = c . height or 0
165 local d = c . depth or 0
166 local thickness = h - d
167 local rulewidth = step * size
168 local slot = { " slot " , id , old }
169 local rule = { " rule " , thickness , rulewidth }
170 local up = upcommand [ xu ]
171 local dn = downcommand [ xd ]
172 local ht = xu + 3 * thickness
173 local dp = 0
174 if not characters [ uprule ] then
175 characters [ uprule ] = {
176 width = rulewidth ,
177 height = ht ,
178 depth = dp ,
179 commands = { push , up , rule , pop } ,
180 }
181 end
182 characters [ upslot ] = {
183 width = w ,
184 height = ht ,
185 depth = dp ,
186 commands = { push , up , slot , pop } ,
187 }
188 local ht = 0
189 local dp = xd + 3 * thickness
190 if not characters [ dnrule ] then
191 characters [ dnrule ] = {
192 width = rulewidth ,
193 height = ht ,
194 depth = dp ,
195 commands = { push , dn , rule , pop }
196 }
197 end
198 characters [ dnslot ] = {
199 width = w ,
200 height = ht ,
201 depth = dp ,
202 commands = { push , dn , slot , pop } ,
203 }
204 end
205end
206
207local function clipped ( main , characters , id , size , unicode , original )
208 local minus = characters [ original ]
209 if minus then
210 local mu = size / 18
211 local step = 3 * mu
212 local width = minus . width
213 if width > step then
214 width = width - step
215 step = step / 2
216 else
217 width = width / 2
218 step = width
219 end
220 characters [ unicode ] = {
221 width = width ,
222 height = minus . height ,
223 depth = minus . depth ,
224 commands = {
225 push ,
226 leftcommand [ step ] ,
227 { " slot " , id , original } ,
228 pop ,
229 }
230 }
231 end
232end
233
234local function raise ( main , characters , id , size , unicode , private , n , id_of_smaller )
235 local raised = fonts . hashes . characters [ main . fonts [ id_of_smaller ] . id ] [ private ]
236 if raised then
237 local up = 0 . 85 * main . parameters . x_height
238 local slot = { " slot " , id_of_smaller , private }
239 local commands = {
240 push , upcommand [ up ] , slot ,
241 }
242 for i = 2 , n do
243 commands [ # commands + 1 ] = slot
244 end
245 commands [ # commands + 1 ] = pop
246 characters [ unicode ] = {
247 width = n * raised . width ,
248 height = ( raised . height or 0 ) + up ,
249 depth = ( raised . depth or 0 ) - up ,
250 italic = raised . italic ,
251 commands = commands ,
252 }
253 end
254end
255
256local function dots ( main , characters , id , size , unicode )
257 local c = characters [ 0x002E ]
258 if c then
259 local w = c . width
260 local h = c . height
261 local d = c . depth
262 local mu = size / 18
263 local right3mu = rightcommand [ 3 * mu ]
264 local right1mu = rightcommand [ 1 * mu ]
265 local up1size = upcommand [ . 1 * size ]
266 local up4size = upcommand [ . 4 * size ]
267 local up7size = upcommand [ . 7 * size ]
268 local right2muw = rightcommand [ 2 * mu + w ]
269 local slot = { " slot " , id , 0x002E }
270 if unicode = = 0x22EF then
271 local c = characters [ 0x022C5 ]
272 if c then
273 local width = c . width
274 local height = c . height
275 local depth = c . depth
276 local slot = { " slot " , id , 0x022C5 }
277 characters [ unicode ] = {
278 width = 3 * width + 2 * 3 * mu ,
279 height = height ,
280 depth = depth ,
281 commands = {
282 push , slot , right3mu , slot , right3mu , slot , pop ,
283 }
284 }
285 end
286 elseif unicode = = 0x22EE then
287
288 characters [ unicode ] = {
289 width = w ,
290 height = h + ( 1 . 4 ) * size ,
291 depth = 0 ,
292 commands = {
293 push , push , slot , pop , up4size , push , slot , pop , up4size , slot , pop ,
294 }
295 }
296 elseif unicode = = 0x22F1 then
297 characters [ unicode ] = {
298 width = 3 * w + 6 * size / 18 ,
299 height = 1 . 5 * size ,
300 depth = 0 ,
301 commands = {
302 push ,
303 right1mu ,
304 push , up7size , slot , pop ,
305 right2muw ,
306 push , up4size , slot , pop ,
307 right2muw ,
308 push , up1size , slot , pop ,
309 right1mu ,
310 pop
311 }
312 }
313 elseif unicode = = 0x22F0 then
314 characters [ unicode ] = {
315 width = 3 * w + 6 * size / 18 ,
316 height = 1 . 5 * size ,
317 depth = 0 ,
318 commands = {
319 push ,
320 right1mu ,
321 push , up1size , slot , pop ,
322 right2muw ,
323 push , up4size , slot , pop ,
324 right2muw ,
325 push , up7size , slot , pop ,
326 right1mu ,
327 pop
328 }
329 }
330 else
331 characters [ unicode ] = {
332 width = 3 * w + 2 * 3 * mu ,
333 height = h ,
334 depth = d ,
335 commands = {
336 push , slot , right3mu , slot , right3mu , slot , pop ,
337 }
338 }
339 end
340 end
341end
342
343local function vertbar ( main , characters , id , size , parent , scale , unicode )
344 local cp = characters [ parent ]
345 if cp then
346 local sc = scale * size
347 local pc = { " slot " , id , parent }
348 characters [ unicode ] = {
349 width = cp . width ,
350 height = cp . height + sc ,
351 depth = cp . depth + sc ,
352 next = cp . next ,
353 commands = {
354 push , upcommand [ sc ] , pc , pop ,
355 push , downcommand [ sc ] , pc , pop ,
356 pc ,
357 } ,
358 }
359 cp . next = unicode
360 end
361end
362
363local function jointwo ( main , characters , id , size , unicode , u1 , d12 , u2 , what )
364 local c1 = characters [ u1 ]
365 local c2 = characters [ u2 ]
366 if c1 and c2 then
367 local w1 = c1 . width
368 local w2 = c2 . width
369 local mu = size / 18
370 characters [ unicode ] = {
371 width = w1 + w2 - d12 * mu ,
372 height = max ( c1 . height or 0 , c2 . height or 0 ) ,
373 depth = max ( c1 . depth or 0 , c2 . depth or 0 ) ,
374 commands = {
375 { " slot " , id , u1 } ,
376 leftcommand [ d12 * mu ] ,
377 { " slot " , id , u2 } ,
378 } ,
379 }
380 end
381end
382
383local function jointhree ( main , characters , id , size , unicode , u1 , d12 , u2 , d23 , u3 )
384 local c1 = characters [ u1 ]
385 local c2 = characters [ u2 ]
386 local c3 = characters [ u3 ]
387 if c1 and c2 and c3 then
388 local w1 = c1 . width
389 local w2 = c2 . width
390 local w3 = c3 . width
391 local mu = size / 18
392 characters [ unicode ] = {
393 width = w1 + w2 + w3 - d12 * mu - d23 * mu ,
394 height = max ( c1 . height or 0 , c2 . height or 0 , c3 . height or 0 ) ,
395 depth = max ( c1 . depth or 0 , c2 . depth or 0 , c3 . depth or 0 ) ,
396 commands = {
397 { " slot " , id , u1 } ,
398 leftcommand [ d12 * mu ] ,
399 { " slot " , id , u2 } ,
400 leftcommand [ d23 * mu ] ,
401 { " slot " , id , u3 } ,
402 }
403 }
404 end
405end
406
407local function stack ( main , characters , id , size , unicode , u1 , d12 , u2 )
408 local c1 = characters [ u1 ]
409 if not c1 then
410 return
411 end
412 local c2 = characters [ u2 ]
413 if not c2 then
414 return
415 end
416 local w1 = c1 . width or 0
417 local h1 = c1 . height or 0
418 local d1 = c1 . depth or 0
419 local w2 = c2 . width or 0
420 local h2 = c2 . height or 0
421 local d2 = c2 . depth or 0
422 local mu = size / 18
423 characters [ unicode ] = {
424 width = w1 ,
425 height = h1 + h2 + d12 ,
426 depth = d1 ,
427 commands = {
428 { " slot " , id , u1 } ,
429 leftcommand [ w1 / 2 + w2 / 2 ] ,
430 downcommand [ - h1 + d2 - d12 * mu ] ,
431 { " slot " , id , u2 } ,
432 }
433 }
434end
435
436local function repeated ( main , characters , id , size , unicode , u , n , private , fraction )
437 local c = characters [ u ]
438 if c then
439 local width = c . width
440 local italic = fraction * width
441 local tc = { " slot " , id , u }
442 local tr = leftcommand [ italic ]
443 local commands = { }
444 for i = 1 , n -1 do
445 commands [ # commands + 1 ] = tc
446 commands [ # commands + 1 ] = tr
447 end
448 commands [ # commands + 1 ] = tc
449 local next = c . next
450 if next then
451 repeated ( main , characters , id , size , private , next , n , private + 1 , fraction )
452 next = private
453 end
454 characters [ unicode ] = {
455 width = width + ( n -1 ) * ( width - italic ) ,
456 height = c . height ,
457 depth = c . depth ,
458 italic = italic ,
459 commands = commands ,
460 next = next ,
461 }
462 end
463end
464
465local function cloned ( main , characters , id , size , source , target )
466 local data = characters [ source ]
467 if data then
468 characters [ target ] = data
469 return true
470 end
471end
472
473
474
475local data_of_smaller = nil
476local size_of_smaller = 0
477
478function vfmath . addmissing ( main , id , size )
479
480 local id_of_smaller = nil
481
482 if size < size_of_smaller or size_of_smaller = = 0 then
483 data_of_smaller = main . fonts [ id ]
484 id_of_smaller = id
485 else
486 id_of_smaller = # main . fonts + 1
487 main . fonts [ id_of_smaller ] = data_of_smaller
488 end
489
490
491
492 local characters = main . characters
493 local shared = main . shared
494 local variables = main . goodies . mathematics and main . goodies . mathematics . variables or { }
495 local joinrelfactor = variables . joinrelfactor or 3
496
497 for i = 0x7A , 0x7D do
498 make ( main , characters , id , size , i , 1 )
499 end
500
501 brace ( main , characters , id , size , 0x23DE , 0xFF17A , 0xFF301 , 0xFF17D , 0xFF17C , 0xFF301 , 0xFF17B )
502 brace ( main , characters , id , size , 0x23DF , 0xFF27C , 0xFF401 , 0xFF27B , 0xFF27A , 0xFF401 , 0xFF27D )
503
504 parent ( main , characters , id , size , 0x23DC , 0xFF17A , 0xFF301 , 0xFF17B )
505 parent ( main , characters , id , size , 0x23DD , 0xFF27C , 0xFF401 , 0xFF27D )
506
507
508 dots ( main , characters , id , size , 0x2026 )
509 dots ( main , characters , id , size , 0x22EE )
510 dots ( main , characters , id , size , 0x22EF )
511 dots ( main , characters , id , size , 0x22F1 )
512 dots ( main , characters , id , size , 0x22F0 )
513
514 vertbar ( main , characters , id , size , 0x0007C , 0 . 10 , 0xFF601 )
515 vertbar ( main , characters , id , size , 0xFF601 , 0 . 30 , 0xFF602 )
516 vertbar ( main , characters , id , size , 0xFF602 , 0 . 30 , 0xFF603 )
517 vertbar ( main , characters , id , size , 0xFF603 , 0 . 30 , 0xFF604 )
518 vertbar ( main , characters , id , size , 0x02016 , 0 . 10 , 0xFF605 )
519 vertbar ( main , characters , id , size , 0xFF605 , 0 . 30 , 0xFF606 )
520 vertbar ( main , characters , id , size , 0xFF606 , 0 . 30 , 0xFF607 )
521 vertbar ( main , characters , id , size , 0xFF607 , 0 . 30 , 0xFF608 )
522
523 clipped ( main , characters , id , size , 0xFF501 , 0x0002D )
524 clipped ( main , characters , id , size , 0xFF502 , 0x02190 )
525 clipped ( main , characters , id , size , 0xFF503 , 0x02192 )
526 clipped ( main , characters , id , size , 0xFF504 , 0xFE321 )
527 clipped ( main , characters , id , size , 0xFF505 , 0xFE322 )
528 clipped ( main , characters , id , size , 0xFF506 , 0xFE323 )
529 clipped ( main , characters , id , size , 0xFF507 , 0xFE324 )
530 clipped ( main , characters , id , size , 0xFF508 , 0x021D0 )
531 clipped ( main , characters , id , size , 0xFF509 , 0x021D2 )
532 clipped ( main , characters , id , size , 0xFF50A , 0x0003D )
533 clipped ( main , characters , id , size , 0xFF50B , 0x0219E )
534 clipped ( main , characters , id , size , 0xFF50C , 0x021A0 )
535 clipped ( main , characters , id , size , 0xFF50D , 0xFF350 )
536 clipped ( main , characters , id , size , 0xFF50E , 0xFF351 )
537 clipped ( main , characters , id , size , 0xFF50F , 0xFF352 )
538 clipped ( main , characters , id , size , 0xFF510 , 0x02261 )
539
540 extension ( main , characters , id , size , 0x2190 , 0xFF502 , 0xFF501 , 0xFF501 )
541 extension ( main , characters , id , size , 0x2192 , 0xFF501 , 0xFF501 , 0xFF503 )
542
543 extension ( main , characters , id , size , 0x002D , 0xFF501 , 0xFF501 , 0xFF501 )
544 extension ( main , characters , id , size , 0x003D , 0xFF50A , 0xFF50A , 0xFF50A )
545 extension ( main , characters , id , size , 0x2261 , 0xFF510 , 0xFF510 , 0xFF510 )
546
547 jointwo ( main , characters , id , size , 0x21A6 , 0xFE321 , 0 , 0x02192 )
548 jointwo ( main , characters , id , size , 0x21A9 , 0x02190 , joinrelfactor , 0xFE323 )
549 jointwo ( main , characters , id , size , 0x21AA , 0xFE322 , joinrelfactor , 0x02192 )
550 jointwo ( main , characters , id , size , 0x27F5 , 0x02190 , joinrelfactor , 0x0002D )
551 jointwo ( main , characters , id , size , 0x27F6 , 0x0002D , joinrelfactor , 0x02192 , 2 )
552 jointwo ( main , characters , id , size , 0x27F7 , 0x02190 , joinrelfactor , 0x02192 )
553 jointwo ( main , characters , id , size , 0x27F8 , 0x021D0 , joinrelfactor , 0x0003D )
554 jointwo ( main , characters , id , size , 0x27F9 , 0x0003D , joinrelfactor , 0x021D2 )
555 jointwo ( main , characters , id , size , 0x27FA , 0x021D0 , joinrelfactor , 0x021D2 )
556 jointhree ( main , characters , id , size , 0x27FB , 0x02190 , joinrelfactor , 0x0002D , 0 , 0xFE324 )
557 jointhree ( main , characters , id , size , 0x27FC , 0xFE321 , 0 , 0x0002D , joinrelfactor , 0x02192 )
558
559 extension ( main , characters , id , size , 0x21A6 , 0xFF504 , 0xFF501 , 0xFF503 )
560 extension ( main , characters , id , size , 0x21A9 , 0xFF502 , 0xFF501 , 0xFF506 )
561 extension ( main , characters , id , size , 0x21AA , 0xFF505 , 0xFF501 , 0xFF503 )
562 extension ( main , characters , id , size , 0x27F5 , 0xFF502 , 0xFF501 , 0xFF501 )
563 extension ( main , characters , id , size , 0x27F6 , 0xFF501 , 0xFF501 , 0xFF503 )
564 extension ( main , characters , id , size , 0x27F7 , 0xFF502 , 0xFF501 , 0xFF503 )
565 extension ( main , characters , id , size , 0x27F8 , 0xFF508 , 0xFF50A , 0xFF50A )
566 extension ( main , characters , id , size , 0x27F9 , 0xFF50A , 0xFF50A , 0xFF509 )
567 extension ( main , characters , id , size , 0x27FA , 0xFF508 , 0xFF50A , 0xFF509 )
568 extension ( main , characters , id , size , 0x27FB , 0xFF502 , 0xFF501 , 0xFF507 )
569 extension ( main , characters , id , size , 0x27FC , 0xFF504 , 0xFF501 , 0xFF503 )
570
571 extension ( main , characters , id , size , 0x219E , 0xFF50B , 0xFF501 , 0xFF501 )
572 extension ( main , characters , id , size , 0x21A0 , 0xFF501 , 0xFF501 , 0xFF50C )
573 extension ( main , characters , id , size , 0x21C4 , 0xFF50D , 0xFF50E , 0xFF50F )
574
575
576
577
578 stack ( main , characters , id , size , 0x2259 , 0x0003D , 3 , 0x02227 )
579
580 jointwo ( main , characters , id , size , 0x22C8 , 0x022B3 , joinrelfactor , 0x022B2 )
581 jointwo ( main , characters , id , size , 0x22A7 , 0x0007C , joinrelfactor , 0x0003D )
582 jointwo ( main , characters , id , size , 0x2260 , 0x00338 , 0 , 0x0003D )
583 jointwo ( main , characters , id , size , 0x2284 , 0x00338 , 0 , 0x02282 )
584 jointwo ( main , characters , id , size , 0x2285 , 0x00338 , 0 , 0x02283 )
585 jointwo ( main , characters , id , size , 0x2209 , 0x00338 , 0 , 0x02208 )
586 jointwo ( main , characters , id , size , 0x2254 , 0x03A , 0 , 0x03D )
587
588 repeated ( main , characters , id , size , 0x222C , 0x222B , 2 , 0xFF800 , 1 / 3 )
589 repeated ( main , characters , id , size , 0x222D , 0x222B , 3 , 0xFF810 , 1 / 3 )
590
591 if cloned ( main , characters , id , size , 0x2032 , 0xFE325 ) then
592 raise ( main , characters , id , size , 0x2032 , 0xFE325 , 1 , id_of_smaller )
593 raise ( main , characters , id , size , 0x2033 , 0xFE325 , 2 , id_of_smaller )
594 raise ( main , characters , id , size , 0x2034 , 0xFE325 , 3 , id_of_smaller )
595
596 characters [ 0xFE932 ] = characters [ 0x2032 ]
597 characters [ 0xFE933 ] = characters [ 0x2033 ]
598 characters [ 0xFE934 ] = characters [ 0x2034 ]
599 end
600
601
602
603
604
605
606 characters [ 0x02B9 ] = characters [ 0x2032 ]
607
608 data_of_smaller = main . fonts [ id ]
609 size_of_smaller = size
610
611end
612
613local unique = 0
614
615local reported = { }
616local reverse = { }
617
618setmetatableindex ( reverse , function ( t , name )
619 if trace_virtual then
620 report_virtual ( " initializing math vector %a " , name )
621 end
622 local m = mathencodings [ name ]
623 local r = { }
624 for u , i in next , m do
625 r [ i ] = u
626 end
627 reverse [ name ] = r
628 return r
629end )
630
631local function copy_glyph ( main , target , original , unicode , slot )
632 local addprivate = fonts . helpers . addprivate
633 local olddata = original [ unicode ]
634 if olddata then
635 local newdata = {
636 width = olddata . width ,
637 height = olddata . height ,
638 depth = olddata . depth ,
639 italic = olddata . italic ,
640 kerns = olddata . kerns ,
641 tounicode = olddata . tounicode ,
642 commands = { { " slot " , slot , unicode } } ,
643 }
644 local glyphdata = newdata
645 local nextglyph = olddata . next
646 while nextglyph do
647 local oldnextdata = original [ nextglyph ]
648 local newnextdata = {
649 width = oldnextdata . width ,
650 height = oldnextdata . height ,
651 depth = oldnextdata . depth ,
652 tounicode = olddata . tounicode ,
653 commands = { { " slot " , slot , nextglyph } } ,
654 }
655 local newnextglyph = addprivate ( main , formatters [ " M-N-%H " ] ( nextglyph ) , newnextdata )
656 newdata . next = newnextglyph
657 local nextnextglyph = oldnextdata . next
658 if nextnextglyph = = nextglyph then
659 break
660 else
661 olddata = oldnextdata
662 newdata = newnextdata
663 nextglyph = nextnextglyph
664 end
665 end
666 local hv = olddata . horiz_variants
667 if hv then
668 hv = fastcopy ( hv )
669 newdata . horiz_variants = hv
670 for i = 1 , # hv do
671 local hvi = hv [ i ]
672 local oldglyph = hvi . glyph
673 local olddata = original [ oldglyph ]
674 local newdata = {
675 width = olddata . width ,
676 height = olddata . height ,
677 depth = olddata . depth ,
678 tounicode = olddata . tounicode ,
679 commands = { { " slot " , slot , oldglyph } } ,
680 }
681 hvi . glyph = addprivate ( main , formatters [ " M-H-%H " ] ( oldglyph ) , newdata )
682 end
683 end
684 local vv = olddata . vert_variants
685 if vv then
686 vv = fastcopy ( vv )
687 newdata . vert_variants = vv
688 for i = 1 , # vv do
689 local vvi = vv [ i ]
690 local oldglyph = vvi . glyph
691 local olddata = original [ oldglyph ]
692 local newdata = {
693 width = olddata . width ,
694 height = olddata . height ,
695 depth = olddata . depth ,
696 tounicode = olddata . tounicode ,
697 commands = { { " slot " , slot , oldglyph } } ,
698 }
699 vvi . glyph = addprivate ( main , formatters [ " M-V-%H " ] ( oldglyph ) , newdata )
700 end
701 end
702 return newdata
703 end
704end
705
706vfmath . copy_glyph = copy_glyph
707
708function vfmath . define ( specification , set , goodies )
709 local name = specification . name
710 local size = specification . size
711 local loaded = { }
712 local fontlist = { }
713 local names = { }
714 local main = nil
715 local start = ( trace_virtual or trace_timings ) and os . clock ( )
716 local okset = { }
717 local n = 0
718 for s = 1 , # set do
719 local ss = set [ s ]
720 local ssname = ss . name
721 if add_optional and ss . optional then
722 if trace_virtual then
723 report_virtual ( " loading font %a subfont %s with name %a at %p is skipped " , name , s , ssname , size )
724 end
725 else
726 if ss . features then
727 ssname = ssname . . " * " . . ss . features
728 end
729 if ss . main then
730 main = s
731 end
732 local alreadyloaded = names [ ssname ]
733 local f , id
734 if alreadyloaded then
735 f , id = alreadyloaded . f , alreadyloaded . id
736 if trace_virtual then
737 report_virtual ( " loading font %a subfont %s with name %a is reused " , name , s , ssname )
738 end
739 else
740 f , id = fonts . constructors . readanddefine ( ssname , size )
741 names [ ssname ] = { f = f , id = id }
742 end
743 if not f or id = = 0 then
744 report_virtual ( " loading font %a subfont %s with name %a at %p is skipped, not found " , name , s , ssname , size )
745 else
746 n = n + 1
747 okset [ n ] = ss
748 loaded [ n ] = f
749 fontlist [ n ] = { id = id , size = size }
750 if not shared [ s ] then
751 shared [ n ] = { }
752 end
753 if trace_virtual then
754 report_virtual ( " loading font %a subfont %s with name %a at %p as id %s using encoding %a " , name , s , ssname , size , id , ss . vector )
755 end
756 if not ss . checked then
757 ss . checked = true
758 local vector = mathencodings [ ss . vector ]
759 if vector then
760
761
762
763 for unicode , index in next , vector do
764 if not tonumber ( index ) then
765 local u = f . unicodes
766 u = u and u [ index ]
767 if u then
768 if trace_virtual then
769 report_virtual ( " resolving name %a to %s " , index , u )
770 end
771 else
772 report_virtual ( " unable to resolve name %a " , index )
773 end
774 vector [ unicode ] = u
775 end
776 end
777 end
778 end
779 end
780 end
781 end
782
783 local parent = loaded [ 1 ] or { }
784 local characters = { }
785 local parameters = { }
786 local mathparameters = { }
787 local descriptions = { }
788 local metadata = { }
789 local properties = { }
790 local goodies = { }
791 local main = {
792 metadata = metadata ,
793 properties = properties ,
794 characters = characters ,
795 descriptions = descriptions ,
796 parameters = parameters ,
797 mathparameters = mathparameters ,
798 fonts = fontlist ,
799 goodies = goodies ,
800 }
801
802
803 for key , value in next , parent do
804 if type ( value ) ~ = " table " then
805 main [ key ] = value
806 end
807 end
808
809 if parent . characters then
810 for unicode , character in next , parent . characters do
811 characters [ unicode ] = character
812 end
813 else
814 report_virtual ( " font %a has no characters " , name )
815 end
816
817 if parent . parameters then
818 for key , value in next , parent . parameters do
819 parameters [ key ] = value
820 end
821 else
822 report_virtual ( " font %a has no parameters " , name )
823 end
824
825 local description = { name = " <unset> " }
826 setmetatableindex ( descriptions , function ( ) return description end )
827
828 if parent . properties then
829 setmetatableindex ( properties , parent . properties )
830 end
831
832 if parent . goodies then
833 setmetatableindex ( goodies , parent . goodies )
834 end
835
836 properties . hasitalics = true
837 properties . hasmath = true
838
839 local fullname = properties . fullname
840 if fullname then
841 unique = unique + 1
842 properties . fullname = fullname . . " - " . . unique
843 end
844
845
846
847 main . fullname = properties . fullname
848 main . nomath = false
849
850 properties . virtualized = true
851 main . type = " virtual "
852
853 parameters . x_height = parameters . x_height or 0
854
855 local already_reported = false
856 local parameters_done = false
857 for s = 1 , n do
858 local ss , fs = okset [ s ] , loaded [ s ]
859 if not fs then
860
861 elseif add_optional and ss . optional then
862
863 else
864 local newparameters = fs . parameters
865 local newmathparameters = fs . mathparameters
866 if newmathparameters then
867 if not parameters_done or ss . parameters then
868 mathparameters = newmathparameters
869 parameters_done = true
870 end
871 elseif not newparameters then
872 report_virtual ( " no parameters set in font %a " , name )
873 elseif ss . extension then
874 mathparameters . math_x_height = newparameters . x_height or 0
875 mathparameters . default_rule_thickness = newparameters [ 8 ] or 0
876 mathparameters . big_op_spacing1 = newparameters [ 9 ] or 0
877 mathparameters . big_op_spacing2 = newparameters [ 10 ] or 0
878 mathparameters . big_op_spacing3 = newparameters [ 11 ] or 0
879 mathparameters . big_op_spacing4 = newparameters [ 12 ] or 0
880 mathparameters . big_op_spacing5 = newparameters [ 13 ] or 0
881
882 elseif ss . parameters then
883 mathparameters . x_height = newparameters . x_height or mathparameters . x_height
884 mathparameters . x_height = mathparameters . x_height or fp . x_height or 0
885 mathparameters . num1 = newparameters [ 8 ] or 0
886 mathparameters . num2 = newparameters [ 9 ] or 0
887 mathparameters . num3 = newparameters [ 10 ] or 0
888 mathparameters . denom1 = newparameters [ 11 ] or 0
889 mathparameters . denom2 = newparameters [ 12 ] or 0
890 mathparameters . sup1 = newparameters [ 13 ] or 0
891 mathparameters . sup2 = newparameters [ 14 ] or 0
892 mathparameters . sup3 = newparameters [ 15 ] or 0
893 mathparameters . sub1 = newparameters [ 16 ] or 0
894 mathparameters . sub2 = newparameters [ 17 ] or 0
895 mathparameters . sup_drop = newparameters [ 18 ] or 0
896 mathparameters . sub_drop = newparameters [ 19 ] or 0
897 mathparameters . delim1 = newparameters [ 20 ] or 0
898 mathparameters . delim2 = newparameters [ 21 ] or 0
899 mathparameters . axis_height = newparameters [ 22 ] or 0
900
901 end
902 if ss . overlay then
903 local fc = fs . characters
904 local first = ss . first
905 if first then
906 local last = ss . last or first
907 for unicode = first , last do
908 characters [ unicode ] = copy_glyph ( main , characters , fc , unicode , s )
909 end
910 else
911 for unicode , data in next , fc do
912 characters [ unicode ] = copy_glyph ( main , characters , fc , unicode , s )
913 end
914 end
915 else
916 local vectorname = ss . vector
917 if vectorname then
918 local offset = 0xFF000
919 local vector = mathencodings [ vectorname ]
920 local rotcev = reverse [ vectorname ]
921 local isextension = ss . extension
922 if vector and rotcev then
923 local fc = fs . characters
924 local fd = fs . descriptions
925 local si = shared [ s ]
926 local fontname = fs . properties . name or " unknown "
927 local skewchar = ss . skewchar
928 for unicode , index in next , vector do
929 local fci = fc [ index ]
930 if not fci then
931 local rf = reported [ fontname ]
932 if not rf then rf = { } reported [ fontname ] = rf end
933 local rv = rf [ vectorname ]
934 if not rv then rv = { } rf [ vectorname ] = rv end
935 local ru = rv [ unicode ]
936 if not ru then
937 if trace_virtual then
938 report_virtual ( " unicode slot %U has no index %H in vector %a for font %a (%S) " , unicode , index , vectorname , fontname , chardata [ unicode ] . description )
939 elseif not already_reported then
940 report_virtual ( " the mapping is incomplete for %a at %p " , name , size )
941 already_reported = true
942 end
943 rv [ unicode ] = true
944 end
945 else
946 local ref = si [ index ]
947 if not ref then
948 ref = { { ' slot ' , s , index } }
949 si [ index ] = ref
950 end
951 local kerns = fci . kerns
952 local width = fci . width
953 local italic = fci . italic
954 if italic and italic > 0 then
955
956 if isextension then
957 width = width + italic
958 end
959 end
960 if kerns then
961 local krn = { }
962 for k , v in next , kerns do
963 local rk = rotcev [ k ]
964 if rk then
965 krn [ rk ] = v
966 end
967 end
968 if not next ( krn ) then
969 krn = nil
970 end
971 local t = {
972 width = width ,
973 height = fci . height ,
974 depth = fci . depth ,
975 italic = italic ,
976 kerns = krn ,
977 commands = ref ,
978 }
979 if skewchar then
980 local k = kerns [ skewchar ]
981 if k then
982 t . top_accent = width / 2 + k
983 end
984 end
985 characters [ unicode ] = t
986 else
987 characters [ unicode ] = {
988 width = width ,
989 height = fci . height ,
990 depth = fci . depth ,
991 italic = italic ,
992 commands = ref ,
993 }
994 end
995 end
996 end
997 if isextension then
998
999 local extension = mathencodings [ " large-to-small " ]
1000 local variants_done = fs . variants_done
1001 for index , fci in next , fc do
1002 if type ( index ) = = " number " then
1003 local ref = si [ index ]
1004 if not ref then
1005 ref = { { ' slot ' , s , index } }
1006 si [ index ] = ref
1007 end
1008 local italic = fci . italic
1009 local t = {
1010 width = fci . width ,
1011 height = fci . height ,
1012 depth = fci . depth ,
1013 italic = italic ,
1014 commands = ref ,
1015 }
1016 local n = fci . next
1017 if n then
1018 t . next = offset + n
1019 elseif variants_done then
1020 local vv = fci . vert_variants
1021 if vv then
1022 t . vert_variants = vv
1023 end
1024 local hv = fci . horiz_variants
1025 if hv then
1026 t . horiz_variants = hv
1027 end
1028 else
1029 local vv = fci . vert_variants
1030 if vv then
1031 for i = 1 , # vv do
1032 local vvi = vv [ i ]
1033 vvi . glyph = vvi . glyph + offset
1034 end
1035 t . vert_variants = vv
1036 end
1037 local hv = fci . horiz_variants
1038 if hv then
1039 for i = 1 , # hv do
1040 local hvi = hv [ i ]
1041 hvi . glyph = hvi . glyph + offset
1042 end
1043 t . horiz_variants = hv
1044 end
1045 end
1046 characters [ offset + index ] = t
1047 end
1048 end
1049 fs . variants_done = true
1050 for unicode , index in next , extension do
1051 local cu = characters [ unicode ]
1052 if cu then
1053 cu . next = offset + index
1054 else
1055 local fci = fc [ index ]
1056 if not fci then
1057
1058 else
1059
1060 local ref = si [ index ]
1061 if not ref then
1062 ref = { { ' slot ' , s , index } }
1063 si [ index ] = ref
1064 end
1065 local kerns = fci . kerns
1066 if kerns then
1067 local krn = { }
1068
1069
1070
1071 for k , v in next , kerns do
1072 krn [ offset + k ] = v
1073 end
1074 characters [ unicode ] = {
1075 width = fci . width ,
1076 height = fci . height ,
1077 depth = fci . depth ,
1078 italic = fci . italic ,
1079 commands = ref ,
1080 kerns = krn ,
1081 next = offset + index ,
1082 }
1083 else
1084 characters [ unicode ] = {
1085 width = fci . width ,
1086 height = fci . height ,
1087 depth = fci . depth ,
1088 italic = fci . italic ,
1089 commands = ref ,
1090 next = offset + index ,
1091 }
1092 end
1093 end
1094 end
1095 end
1096 end
1097 else
1098 report_virtual ( " error in loading %a, problematic vector %a " , name , vectorname )
1099 end
1100 end
1101 end
1102 mathematics . extras . copy ( main )
1103 end
1104 end
1105
1106 main . mathparameters = mathparameters
1107
1108
1109
1110 fontlist [ # fontlist + 1 ] = {
1111
1112 id = 0 ,
1113 size = size ,
1114 }
1115 vfmath . addmissing ( main , # fontlist , size )
1116
1117 mathematics . addfallbacks ( main )
1118
1119 main . properties . math_is_scaled = true
1120 fonts . constructors . assignmathparameters ( main , main )
1121
1122 main . MathConstants = main . mathparameters
1123
1124 if trace_virtual or trace_timings then
1125 report_virtual ( " loading and virtualizing font %a at size %p took %0.3f seconds " , name , size , os . clock ( ) - start )
1126 end
1127
1128 main . oldmath = true
1129 return main
1130end
1131
1132function mathematics . makefont ( name , set , goodies )
1133 fonts . definers . methods . variants [ name ] = function ( specification )
1134 return vfmath . define ( specification , set , goodies )
1135 end
1136end
1137
1138
1139
1140function vfmath . setletters ( font_encoding , name , uppercase , lowercase )
1141 local enc = font_encoding [ name ]
1142 for i = 0 , 25 do
1143 enc [ uppercase + i ] = i + 0x41
1144 enc [ lowercase + i ] = i + 0x61
1145 end
1146end
1147
1148function vfmath . setdigits ( font_encoding , name , digits )
1149 local enc = font_encoding [ name ]
1150 for i = 0 , 9 do
1151 enc [ digits + i ] = i + 0x30
1152 end
1153end
1154 |