1if not modules then modules = { } end modules ['font-tpk'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to font-lib.mkiv",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10
11
12
13
14
15local next = next
16local extract, band, lshift, rshift = bit32.extract, bit32.band, bit32.lshift, bit32.rshift
17local idiv = number.idiv
18local char = string.char
19local concat, insert, remove, copy = table.concat, table.insert, table.remove, table.copy
20local tobitstring = number.tobitstring
21local formatters = string.formatters
22local round = math.round
23
24local streams = utilities.streams
25local openstream = streams.open
26local streamsize = streams.size
27local readcardinal1 = streams.readcardinal1
28local readcardinal2 = streams.readcardinal2
29local readcardinal3 = streams.readcardinal3
30local readcardinal4 = streams.readcardinal4
31local readinteger1 = streams.readinteger1
32local readinteger2 = streams.readinteger2
33local readinteger3 = streams.readinteger3
34local readinteger4 = streams.readinteger4
35local readbyte = streams.readbyte
36local readbytes = streams.readbytes
37local readstring = streams.readstring
38local skipbytes = streams.skipbytes
39local getposition = streams.getposition
40local setposition = streams.setposition
41
42if not fonts then fonts = { handlers = { tfm = { } } } end
43
44local handlers = fonts.handlers
45local tfm = handlers.tfm or { }
46handlers.tfm = tfm
47local readers = tfm.readers or { }
48tfm.readers = readers
49
50tfm.version = 1.005
51tfm.cache = containers.define("fonts", "tfm", tfm.version, true)
52
53
54
55
56do
57
58 local function readbitmap(glyph,s,flagbyte)
59
60 local inputbyte = 0
61 local bitweight = 0
62 local dynf = 0
63 local remainder = 0
64 local realfunc = nil
65 local repeatcount = 0
66
67 local function getnyb()
68 if bitweight == 0 then
69 bitweight = 16
70 inputbyte = readbyte(s)
71 return extract(inputbyte,4,4)
72 else
73 bitweight = 0
74 return band(inputbyte,15)
75 end
76 end
77
78 local function getbit()
79 bitweight = rshift(bitweight,1)
80 if bitweight == 0 then
81 inputbyte = readbyte(s)
82 bitweight = 128
83 end
84 return band(inputbyte,bitweight)
85 end
86
87 local function pkpackednum()
88 local i = getnyb(s)
89 if i == 0 then
90 repeat
91 j = getnyb()
92 i = i + 1
93 until (j ~= 0)
94 if i > 3 then
95 return handlehuge(i,j)
96 else
97 for i=1,i do
98 j = j * 16 + getnyb()
99 end
100 return j - 15 + (13 - dynf) * 16 + dynf
101 end
102 elseif i <= dynf then
103 return i
104 elseif i < 14 then
105 return (i - dynf - 1) * 16 + getnyb() + dynf + 1
106 elseif i == 14 then
107 repeatcount = pkpackednum()
108 else
109 repeatcount = 1
110 end
111 return realfunc()
112 end
113
114 local function rest()
115 if remainder < 0 then
116 remainder = -remainder
117 return 0
118 elseif remainder > 4000 then
119 remainder = 4000 - remainder
120 return 4000
121 elseif remainder > 0 then
122 local i = remainder
123 remainder = 0
124 realfunc = pkpackednum
125 return i
126 else
127
128 return 0
129 end
130 end
131
132 local function handlehuge(i,j)
133 while i ~= 0 do
134 j = lshift(j,4) + getnyb()
135
136 i = i - 1
137 end
138 remainder = j - 15 + (13 - dynf) * 16 + dynf
139 realfunc = rest
140 return rest()
141 end
142
143 local gpower = { [0] =
144 0, 1, 3, 7, 15, 31, 63, 127,
145 255, 511, 1023, 2047, 4095, 8191, 16383, 32767,
146 65535
147 }
148
149 local raster = { }
150 local r = 0
151 glyph.stream = raster
152
153 local xsize = glyph.xsize
154 local ysize = glyph.ysize
155 local word = 0
156 local wordweight = 0
157 local wordwidth = idiv(xsize + 15,16)
158 local rowsleft = 0
159 local turnon = band(flagbyte,8) == 8 and true or false
160 local hbit = 0
161 local count = 0
162
163 realfunc = pkpackednum
164 dynf = idiv(flagbyte,16)
165
166 if dynf == 14 then
167 bitweight = 0
168 for i=1,ysize do
169 word = 0
170 wordweight = 32768
171 for j=1,xsize do
172 if getbit() ~= 0 then
173 word = word + wordweight
174 end
175 wordweight = rshift(wordweight,1)
176 if wordweight == 0 then
177 r = r + 1
178 raster[r] = word
179 word = 0
180 wordweight = 32768
181 end
182 end
183 if wordweight ~= 32768 then
184 r = r + 1
185 raster[r] = word
186 end
187 end
188 else
189 rowsleft = ysize
190 hbit = xsize
191 repeatcount = 0
192 wordweight = 16
193 word = 0
194 bitweight = 0
195 while rowsleft > 0 do
196 count = realfunc()
197 while count ~= 0 do
198 if count < wordweight and count < hbit then
199 if turnon then
200 word = word + gpower[wordweight] - gpower[wordweight - count]
201 end
202 hbit = hbit - count
203 wordweight = wordweight - count
204 count = 0
205 elseif count >= hbit and hbit <= wordweight then
206 if turnon then
207 word = word + gpower[wordweight] - gpower[wordweight - hbit]
208 end
209 r = r + 1
210 raster[r] = word
211 for i=1,repeatcount*wordwidth do
212 r = r + 1
213 raster[r] = raster[r - wordwidth]
214 end
215 rowsleft = rowsleft - repeatcount - 1
216 repeatcount = 0
217 word = 0
218 wordweight = 16
219 count = count - hbit
220 hbit = xsize
221 else
222 if turnon then
223 word = word + gpower[wordweight]
224 end
225 r = r + 1
226 raster[r] = word
227 word = 0
228 count = count - wordweight
229 hbit = hbit - wordweight
230 wordweight = 16
231 end
232 end
233 turnon = not turnon
234 end
235 if rowsleft ~= 0 or hbit ~= xsize then
236 print("ERROR",rowsleft,hbit,xsize)
237
238 end
239 end
240
241 end
242
243 function readers.showpk(glyph)
244 local xsize = glyph.xsize
245 local ysize = glyph.ysize
246 local stream = glyph.stream
247 local result = { }
248 local rr = { }
249 local r = 0
250 local s = 0
251 local cw = idiv(xsize+ 7, 8)
252 local rw = idiv(xsize+15,16)
253 local extra = 2 * rw == cw
254 local b
255 for y=1,ysize do
256 r = 0
257 for x=1,rw-1 do
258 s = s + 1 ; b = stream[s]
259 r = r + 1 ; rr[r] = tobitstring(b,16,16)
260 end
261 s = s + 1 ; b = stream[s]
262 if extra then
263 r = r + 1 ; rr[r] = tobitstring(b,16,16)
264 else
265 r = r + 1 ; rr[r] = tobitstring(extract(b,8+(8-cw),cw),cw,cw)
266 end
267 result[y] = concat(rr)
268 end
269 return concat(result,"\n")
270 end
271
272 local template = formatters [ [[
273%.3N 0 %i %i %i %i d1
274q
275%i 0 0 %i %i %i cm
276BI
277 /W %i
278 /H %i
279 /IM true
280 /BPC 1
281 /D [1 0]
282ID %t
283EI
284Q]] ]
285
286 function readers.pktopdf(glyph,data,factor)
287 local width = data.width * factor
288 local xsize = glyph.xsize or 0
289 local ysize = glyph.ysize or 0
290 local xoffset = glyph.xoffset or 0
291 local yoffset = glyph.yoffset or 0
292 local stream = glyph.stream
293
294 local dpi = 1
295 local newdpi = 1
296
297 local xdpi = dpi * xsize / newdpi
298 local ydpi = dpi * ysize / newdpi
299
300 local llx = - xoffset
301 local lly = yoffset - ysize + 1
302 local urx = llx + xsize + 1
303 local ury = lly + ysize
304
305 local result = { }
306 local r = 0
307 local s = 0
308 local cw = idiv(xsize+ 7, 8)
309 local rw = idiv(xsize+15,16)
310 local extra = 2 * rw == cw
311 local b
312 for y=1,ysize do
313 for x=1,rw-1 do
314 s = s + 1 ; b = stream[s]
315 r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8))
316 end
317 s = s + 1 ; b = stream[s]
318 if extra then
319 r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8))
320 else
321 r = r + 1 ; result[r] = char(extract(b,8,8))
322 end
323 end
324 return template(width,llx,lly,urx,ury,xdpi,ydpi,llx,lly,xsize,ysize,result), width
325 end
326
327 function readers.loadpk(filename)
328 local s = openstream(filename)
329 local preamble = readcardinal1(s)
330 local version = readcardinal1(s)
331 local comment = readstring(s,readcardinal1(s))
332 local designsize = readcardinal4(s)
333 local checksum = readcardinal4(s)
334 local hppp = readcardinal4(s)
335 local vppp = readcardinal4(s)
336 if preamble ~= 247 or version ~= 89 or not vppp then
337 return { error = "invalid preamble" }
338 end
339 local glyphs = { }
340 local data = {
341 designsize = designsize,
342 comment = comment,
343 hppp = hppp,
344 vppp = vppp,
345 glyphs = glyphs,
346 }
347 while true do
348 local flagbyte = readcardinal1(s)
349 if flagbyte < 240 then
350 local c = band(flagbyte,7)
351 local length, index, width, pixels, xsize, ysize, xoffset, yoffset
352 if c >= 0 and c <= 3 then
353 length = band(flagbyte,7) * 256 + readcardinal1(s) - 3
354 index = readcardinal1(s)
355 width = readinteger3(s)
356 pixels = readcardinal1(s)
357 xsize = readcardinal1(s)
358 ysize = readcardinal1(s)
359 xoffset = readcardinal1(s)
360 yoffset = readcardinal1(s)
361 if xoffset > 127 then
362 xoffset = xoffset - 256
363 end
364 if yoffset > 127 then
365 yoffset = yoffset - 256
366 end
367 elseif c >= 4 and c <= 6 then
368 length = band(flagbyte,3) * 65536 + readcardinal1(s) * 256 + readcardinal1(s) - 4
369 index = readcardinal1(s)
370 width = readinteger3(s)
371 pixels = readcardinal2(s)
372 xsize = readcardinal2(s)
373 ysize = readcardinal2(s)
374 xoffset = readcardinal2(s)
375 yoffset = readcardinal2(s)
376 else
377 length = readcardinal4(s) - 9
378 index = readcardinal4(s)
379 width = readinteger4(s)
380 pixels = readcardinal4(s)
381 readcardinal4(s)
382 xsize = readcardinal4(s)
383 ysize = readcardinal4(s)
384 xoffset = readcardinal4(s)
385 yoffset = readcardinal4(s)
386 end
387 local glyph = {
388 index = index,
389 width = width,
390 pixels = pixels,
391 xsize = xsize,
392 ysize = ysize,
393 xoffset = xoffset,
394 yoffset = yoffset,
395 }
396 if length <= 0 then
397 data.error = "bad packet"
398 return data
399 end
400 readbitmap(glyph,s,flagbyte)
401 glyphs[index] = glyph
402 elseif flagbyte == 240 then
403
404 skipbytes(s,readcardinal1(s))
405 elseif flagbyte == 241 then
406
407 skipbytes(s,readcardinal2(s)*2)
408 elseif flagbyte == 242 then
409
410 skipbytes(s,readcardinal3(s)*3)
411 elseif flagbyte == 243 then
412
413 skipbytes(s,readcardinal4(s)*4)
414 elseif flagbyte == 244 then
415
416 skipbytes(s,4)
417 elseif flagbyte == 245 then
418 break
419 elseif flagbyte == 246 then
420
421 else
422 data.error = "unknown pk command"
423 break
424 end
425 end
426 return data
427 end
428
429end
430
431do
432
433 local leftboundary = -1
434 local rightboundary = -2
435 local boundarychar = 65536
436
437 function readers.loadtfm(filename)
438 local data
439
440 local function someerror(m)
441 if not data then
442 data = { }
443 end
444 data.error = m or "fatal error"
445 return data
446 end
447
448 local s = openstream(filename)
449 if not s then
450 return someerror()
451 end
452
453 local wide = false
454 local header = 0
455 local max = 0
456 local size = streamsize(s)
457 local glyphs = table.setmetatableindex(function(t,k)
458 local v = {
459
460 width = 0,
461 height = 0,
462 depth = 0,
463 italic = 0,
464 }
465 t[k] = v
466 return v
467 end)
468 local parameters = { }
469 local direction = 0
470
471 local lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np
472
473 lf = readcardinal2(s)
474 if lf ~= 0 then
475 header = 6
476 max = 255
477 wide = false
478 lh = readcardinal2(s)
479 bc = readcardinal2(s)
480 ec = readcardinal2(s)
481 nw = readcardinal2(s)
482 nh = readcardinal2(s)
483 nd = readcardinal2(s)
484 ni = readcardinal2(s)
485 nl = readcardinal2(s)
486 nk = readcardinal2(s)
487 ne = readcardinal2(s)
488 np = readcardinal2(s)
489 else
490 header = 14
491 max = 65535
492 wide = readcardinal4(s) == 0
493 if not wide then
494 return someerror("invalid format")
495 end
496 lf = readcardinal4(s)
497 lh = readcardinal4(s)
498 bc = readcardinal4(s)
499 ec = readcardinal4(s)
500 nw = readcardinal4(s)
501 nh = readcardinal4(s)
502 nd = readcardinal4(s)
503 ni = readcardinal4(s)
504 nl = readcardinal4(s)
505 nk = readcardinal4(s)
506 ne = readcardinal4(s)
507 np = readcardinal4(s)
508 direction = readcardinal4(s)
509 end
510 if (bc > ec + 1) or (ec > max) then
511 return someerror("file is too small")
512 end
513 if bc > max then
514 bc, ec = 1, 0
515 end
516 local nlw = (wide and 2 or 1) * nl
517 local neew = (wide and 2 or 1) * ne
518 local ncw = (wide and 2 or 1) * (ec - bc + 1)
519 if lf ~= (header + lh + ncw + nw + nh + nd + ni + nlw + nk + neew + np) then
520 return someerror("file is too small")
521 end
522 if nw == 0 or nh == 0 or nd == 0 or ni == 0 then
523 return someerror("no glyphs")
524 end
525 if lf * 4 > size then
526 return someerror("file is too small")
527 end
528 local slh = lh
529 if lh < 2 then
530 return someerror("file is too small")
531 end
532 local checksum = readcardinal4(s)
533 local designsize = readcardinal2(s)
534 designsize = designsize * 256 + readcardinal1(s)
535 designsize = designsize * 16 + rshift(readcardinal1(s),4)
536 if designsize < 0xFFFF then
537 return someerror("weird designsize")
538 end
539
540 local alpha = 16
541 local z = designsize
542 while z >= 040000000 do
543 z = rshift(z,1)
544 alpha = alpha + alpha
545 end
546 local beta = idiv(256,alpha)
547 alpha = alpha * z
548
549 local function readscaled()
550 local a, b, c, d = readbytes(s,4)
551 local n = idiv(rshift(rshift(d*z,8)+c*z,8)+b*z,beta)
552 if a == 0 then
553 return n
554 elseif a == 255 then
555 return n - alpha
556 else
557 return 0
558 end
559 end
560
561 local function readunscaled()
562 local a, b, c, d = readbytes(s,4)
563 if a > 127 then
564 a = a - 256
565 end
566 return a * 0xFFFFF + b * 0xFFF + c * 0xF + rshift(d,4)
567 end
568
569 while lh > 2 do
570 skipbytes(s,4)
571 lh = lh - 1
572 end
573 local saved = getposition(s)
574 setposition(s,(header + slh + ncw) * 4 + 1)
575 local widths = { } for i=0,nw-1 do widths [i] = readscaled() end
576 local heights = { } for i=0,nh-1 do heights[i] = readscaled() end
577 local depths = { } for i=0,nd-1 do depths [i] = readscaled() end
578 local italics = { } for i=0,ni-1 do italics[i] = readscaled() end
579 if widths[0] ~= 0 or heights[0] ~= 0 or depths[0] ~= 0 then
580 return someerror("invalid dimensions")
581 end
582
583 local blabel = nl
584 local bchar = boundarychar
585
586 local ligatures = { }
587 if nl > 0 then
588 for i=0,nl-1 do
589 local a, b, c, d = readbytes(s,4)
590 ligatures[i] = {
591 skip = a,
592 nxt = b,
593 op = c,
594 rem = d,
595 }
596 if a > 128 then
597 if 256 * c + d >= nl then
598 return someerror("invalid ligature table")
599 end
600 if a == 255 and i == 0 then
601 bchar = b
602 end
603 else
604 if c < 128 then
605
606 elseif 256 * (c - 128) + d >= nk then
607 return someerror("invalid ligature table")
608 end
609 if (a < 128) and (i - 0 + a + 1 >= nl) then
610 return someerror("invalid ligature table")
611 end
612 end
613 if a == 255 then
614 blabel = 256 * c + d
615 end
616 end
617 end
618 local allkerns = { }
619 for i=0,nk-1 do
620 allkerns[i] = readscaled()
621 end
622 local extensibles = { }
623 for i=0,ne-1 do
624 extensibles[i] = wide and {
625 top = readcardinal2(s),
626 bot = readcardinal2(s),
627 mid = readcardinal2(s),
628 rep = readcardinal2(s),
629 } or {
630 top = readcardinal1(s),
631 bot = readcardinal1(s),
632 mid = readcardinal1(s),
633 rep = readcardinal1(s),
634 }
635 end
636 for i=1,np do
637 if i == 1 then
638 parameters[i] = readunscaled()
639 else
640 parameters[i] = readscaled()
641 end
642 end
643 for i=1,7 do
644 if not parameters[i] then
645 parameters[i] = 0
646 end
647 end
648
649 setposition(s,saved)
650 local extras = false
651 if blabel ~= nl then
652 local k = blabel
653 while true do
654 local l = ligatures[k]
655 local skip = l.skip
656 if skip <= 128 then
657
658
659
660 extras = true
661
662 end
663 if skip == 0 then
664 k = k + 1
665 else
666 if skip >= 128 then
667 break
668 end
669 k = k + skip + 1
670 end
671 end
672 end
673 if extras then
674 local ligas = { }
675 local kerns = { }
676 local k = blabel
677 while true do
678 local l = ligatures[k]
679 local skip = l.skip
680 if skip <= 128 then
681 local nxt = l.nxt
682 local op = l.op
683 local rem = l.rem
684 if op >= 128 then
685 kerns[nxt] = allkerns[256 * (op - 128) + rem]
686 else
687 ligas[nxt] = { type = op * 2 + 1, char = rem }
688 end
689 end
690 if skip == 0 then
691 k = k + 1
692 else
693 if skip >= 128 then
694 break;
695 end
696 k = k + skip + 1
697 end
698 end
699 if next(kerns) then
700 local glyph = glyphs[leftboundary]
701 glyph.kerns = kerns
702 glyph.remainder = 0
703 end
704 if next(ligas) then
705 local glyph = glyphs[leftboundary]
706 glyph.ligatures = ligas
707 glyph.remainder = 0
708 end
709 end
710 for i=bc,ec do
711 local glyph, width, height, depth, italic, tag, remainder
712 if wide then
713 width = readcardinal2(s)
714 height = readcardinal1(s)
715 depth = readcardinal1(s)
716 italic = readcardinal1(s)
717 tag = readcardinal1(s)
718 remainder = readcardinal2(s)
719 else
720 width = readcardinal1(s)
721 height = readcardinal1(s)
722 depth = extract(height,0,4)
723 height = extract(height,4,4)
724 italic = readcardinal1(s)
725 tag = extract(italic,0,2)
726 italic = extract(italic,2,6)
727 remainder = readcardinal1(s)
728 end
729 if width == 0 then
730
731 else
732 if width >= nw or height >= nh or depth >= nd or italic >= ni then
733 return someerror("invalid dimension index")
734 end
735 local extensible, nextinsize
736 if tag == 0 then
737
738 else
739 local r = remainder
740 if tag == 1 then
741 if r >= nl then
742 return someerror("invalid ligature index")
743 end
744 elseif tag == 2 then
745 if r < bc or r > ec then
746 return someerror("invalid chain index")
747 end
748 while r < i do
749 local g = glyphs[r]
750 if g.tag ~= list_tag then
751 break
752 end
753 r = g.remainder
754 end
755 if r == i then
756 return someerror("cycles in chain")
757 end
758 nextinsize = r
759 elseif tag == 3 then
760 if r >= ne then
761 return someerror("bad extensible")
762 end
763 extensible = extensibles[r]
764 remainder = 0
765 end
766 end
767 glyphs[i] = {
768 width = widths [width],
769 height = heights[height],
770 depth = depths [depth],
771 italic = italics[italic],
772 tag = tag,
773
774 remainder = remainder,
775 extensible = extensible,
776 next = nextinsize,
777 }
778 end
779 end
780 for i=bc,ec do
781 local glyph = glyphs[i]
782 if glyph.tag == 1 then
783
784 local k = glyph.remainder
785 local l = ligatures[k]
786 if l.skip > 128 then
787 k = 256 * l.op + l.rem
788 end
789 local ligas = { }
790 local kerns = { }
791 while true do
792 local l = ligatures[k]
793 local skip = l.skip
794 if skip <= 128 then
795 local nxt = l.nxt
796 local op = l.op
797 local rem = l.rem
798 if op >= 128 then
799 local kern = allkerns[256 * (op - 128) + rem]
800 if nxt == bchar then
801 kerns[rightboundary] = kern
802 end
803 kerns[nxt] = kern
804 else
805 local ligature = { type = op * 2 + 1, char = rem }
806 if nxt == bchar then
807 ligas[rightboundary] = ligature
808 end
809 ligas[nxt] = ligature
810 end
811 end
812 if skip == 0 then
813 k = k + 1
814 else
815 if skip >= 128 then
816 break
817 end
818 k = k + skip + 1
819 end
820 end
821 if next(kerns)then
822 glyph.kerns = kerns
823 glyph.remainder = 0
824 end
825 if next(ligas) then
826 glyph.ligatures = ligas
827 glyph.remainder = 0
828 end
829 end
830 end
831
832 if bchar ~= boundarychar then
833 glyphs[rightboundary] = copy(glyphs[bchar])
834 end
835
836
837
838
839
840
841 return {
842 name = file.nameonly(filename),
843 fontarea = file.pathpart(filename),
844 glyphs = glyphs,
845 parameters = parameters,
846 designsize = designsize,
847 size = designsize,
848 direction = direction,
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864 }
865 end
866
867end
868
869do
870
871 local push = { "push" }
872 local push = { "pop" }
873
874 local w, x, y, z, f
875 local stack
876 local s, result, r
877 local alpha, beta, z
878
879 local function scaled1()
880 local a = readbytes(s,1)
881 if a == 0 then
882 return 0
883 elseif a == 255 then
884 return - alpha
885 else
886 return 0
887 end
888 end
889
890 local function scaled2()
891 local a, b = readbytes(s,2)
892 local sw = idiv(b*z,beta)
893 if a == 0 then
894 return sw
895 elseif a == 255 then
896 return sw - alpha
897 else
898 return 0
899 end
900 end
901
902 local function scaled3()
903 local a, b, c = readbytes(s,3)
904 local sw = idiv(rshift(c*z,8)+b*z,beta)
905 if a == 0 then
906 return sw
907 elseif a == 255 then
908 return sw - alpha
909 else
910 return 0
911 end
912 end
913
914 local function scaled4()
915 local a, b, c, d = readbytes(s,4)
916 local sw = idiv( rshift(rshift(d*z,8)+(c*z),8)+b*z,beta)
917 if a == 0 then
918 return sw
919 elseif a == 255 then
920 return sw - alpha
921 else
922 return 0
923 end
924 end
925
926 local function dummy()
927 end
928
929 local actions = {
930
931 [128] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) } p = p + 1 end,
932 [129] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) } p = p + 2 end,
933 [130] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal3(s) } p = p + 3 end,
934 [131] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) } p = p + 4 end,
935
936 [132] = function()
937 r = r + 1
938 result[r] = { "rule", scaled4(), scaled4() }
939 p = p + 8
940 end,
941
942 [133] = function()
943 r = r + 1 result[r] = push
944 r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) }
945 r = r + 1 result[r] = pop
946 p = p + 1
947 end,
948 [134] = function()
949 r = r + 1 result[r] = push
950 r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) }
951 r = r + 1 result[r] = pop
952 p = p + 2
953 end,
954 [135] = function()
955 r = r + 1 result[r] = push
956 r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) }
957 r = r + 1 result[r] = pop
958 p = p + 3
959 end,
960 [136] = function()
961 r = r + 1 result[r] = push
962 r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) }
963 r = r + 1 result[r] = pop
964 p = p + 4
965 end,
966
967 [137] = function()
968 r = r + 1 result[r] = push
969 r = r + 1 result[r] = { "rule", scaled4(), scaled4() }
970 r = r + 1 result[r] = pop
971 p = p + 8
972 end,
973
974 [138] = dummy,
975 [139] = dummy,
976 [140] = dummy,
977
978 [141] = function()
979 insert(stack, { w, x, y, z })
980 r = r + 1
981 result[r] = push
982 end,
983 [142] = function()
984 local t = remove(stack)
985 if t then
986 w, x, y, z = t[1], t[2], t[3], t[4]
987 r = r + 1
988 result[r] = pop
989 end
990 end,
991
992 [143] = function() r = r + 1 result[r] = { "right", scaled1() } p = p + 1 end,
993 [144] = function() r = r + 1 result[r] = { "right", scaled2() } p = p + 2 end,
994 [145] = function() r = r + 1 result[r] = { "right", scaled3() } p = p + 3 end,
995 [146] = function() r = r + 1 result[r] = { "right", scaled4() } p = p + 4 end,
996
997 [148] = function() w = scaled1() r = r + 1 result[r] = { "right", w } p = p + 1 end,
998 [149] = function() w = scaled2() r = r + 1 result[r] = { "right", w } p = p + 2 end,
999 [150] = function() w = scaled3() r = r + 1 result[r] = { "right", w } p = p + 3 end,
1000 [151] = function() w = scaled4() r = r + 1 result[r] = { "right", w } p = p + 4 end,
1001
1002 [153] = function() x = scaled1() r = r + 1 result[r] = { "right", x } p = p + 1 end,
1003 [154] = function() x = scaled2() r = r + 1 result[r] = { "right", x } p = p + 2 end,
1004 [155] = function() x = scaled3() r = r + 1 result[r] = { "right", x } p = p + 3 end,
1005 [156] = function() x = scaled4() r = r + 1 result[r] = { "right", x } p = p + 4 end,
1006
1007 [157] = function() r = r + 1 result[r] = { "down", scaled1() } p = p + 1 end,
1008 [158] = function() r = r + 1 result[r] = { "down", scaled2() } p = p + 2 end,
1009 [159] = function() r = r + 1 result[r] = { "down", scaled3() } p = p + 3 end,
1010 [160] = function() r = r + 1 result[r] = { "down", scaled4() } p = p + 4 end,
1011
1012 [162] = function() y = scaled1() r = r + 1 result[r] = { "down", y } p = p + 1 end,
1013 [163] = function() y = scaled2() r = r + 1 result[r] = { "down", y } p = p + 2 end,
1014 [164] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 3 end,
1015 [165] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 4 end,
1016
1017 [167] = function() z = scaled1() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1018 [168] = function() z = scaled2() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1019 [169] = function() z = scaled3() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1020 [170] = function() z = scaled4() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1021
1022 [147] = function() r = r + 1 result[r] = { "right", w } end,
1023 [152] = function() r = r + 1 result[r] = { "right", x } end,
1024 [161] = function() r = r + 1 result[r] = { "down", y } end,
1025 [166] = function() r = r + 1 result[r] = { "down", z } end,
1026
1027 [235] = function() f = readcardinal1(s) p = p + 1 end,
1028 [236] = function() f = readcardinal2(s) p = p + 3 end,
1029 [237] = function() f = readcardinal3(s) p = p + 3 end,
1030 [238] = function() f = readcardinal4(s) p = p + 4 end,
1031
1032 [239] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 1 + n end,
1033 [240] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 2 + n end,
1034 [241] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 3 + n end,
1035 [242] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 4 + n end,
1036
1037 [250] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 1 + n end,
1038 [251] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 2 + n end,
1039 [252] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 3 + n end,
1040 [253] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 4 + n end,
1041
1042 }
1043
1044 table.setmetatableindex(actions,function(t,cmd)
1045 local v
1046 if cmd >= 0 and cmd <= 127 then
1047 v = function()
1048 if f == 0 then
1049 f = 1
1050 end
1051 r = r + 1 ; result[r] = { "slot", f, cmd }
1052 end
1053 elseif cmd >= 171 and cmd <= 234 then
1054 cmd = cmd - 170
1055 v = function()
1056 r = r + 1 ; result[r] = { "font", cmd }
1057 end
1058 else
1059 v = dummy
1060 end
1061 t[cmd] = v
1062 return v
1063 end)
1064
1065 function readers.loadvf(filename,data)
1066
1067 local function someerror(m)
1068 if not data then
1069 data = { }
1070 end
1071 data.error = m or "fatal error"
1072 return data
1073 end
1074
1075 s = openstream(filename)
1076 if not s then
1077 return someerror()
1078 end
1079
1080 local cmd = readcardinal1(s)
1081 if cmd ~= 247 then
1082 return someerror("bad preamble")
1083 end
1084 cmd = readcardinal1(s)
1085 if cmd ~= 202 then
1086 return someerror("bad version")
1087 end
1088 local header = readstring(s,readcardinal1(s))
1089 local checksum = readcardinal4(s)
1090 local designsize = idiv(readcardinal4(s),16)
1091 local fonts = data and data.fonts or { }
1092 local glyphs = data and data.glyphs or { }
1093
1094 alpha = 16
1095 z = designsize
1096 while z >= 040000000 do
1097 z = rshift(z,1)
1098 alpha = alpha + alpha
1099 end
1100 beta = idiv(256,alpha)
1101 alpha = alpha * z
1102
1103 cmd = readcardinal1(s)
1104 while true do
1105 local n
1106 if cmd == 243 then
1107 n = readcardinal1(s) + 1
1108 elseif cmd == 244 then
1109 n = readcardinal2(s) + 1
1110 elseif cmd == 245 then
1111 n = readcardinal3(s) + 1
1112 elseif cmd == 246 then
1113 n = readcardinal4(s) + 1
1114 else
1115 break
1116 end
1117 local checksum = skipbytes(s,4)
1118 local size = scaled4()
1119 local designsize = idiv(readcardinal4(s),16)
1120 local pathlen = readcardinal1(s)
1121 local namelen = readcardinal1(s)
1122 local path = readstring(s,pathlen)
1123 local name = readstring(s,namelen)
1124 fonts[n] = { path = path, name = name, size = size }
1125 cmd = readcardinal1(s)
1126 end
1127 local index = 0
1128 while cmd and cmd <= 242 do
1129 local width = 0
1130 local length = 0
1131 local checksum = 0
1132 if cmd == 242 then
1133 length = readcardinal4(s)
1134 checksum = readcardinal4(s)
1135 width = readcardinal4(s)
1136 else
1137 length = cmd
1138 checksum = readcardinal1(s)
1139 width = readcardinal3(s)
1140 end
1141 w, x, y, z, f = 0, 0, 0, 0, false
1142 stack, result, r, p = { }, { }, 0, 0
1143 while p < length do
1144 local cmd = readcardinal1(s)
1145 p = p + 1
1146 actions[cmd]()
1147 end
1148 local glyph = glyphs[index]
1149 if glyph then
1150 glyph.width = width
1151 glyph.commands = result
1152 else
1153 glyphs[index] = {
1154 width = width,
1155 commands = result,
1156 }
1157 end
1158 index = index + 1
1159 if #stack > 0 then
1160
1161 end
1162 if packet_length ~= 0 then
1163
1164 end
1165 cmd = readcardinal1(s)
1166 end
1167 if readcardinal1(s) ~= 248 then
1168
1169 end
1170 s, result, r = nil, nil, nil
1171 if data then
1172 data.glyphs = data.glyphs or glyphs
1173 data.fonts = data.fonts or fonts
1174 return data
1175 else
1176 return {
1177 name = file.nameonly(filename),
1178 fontarea = file.pathpart(filename),
1179 glyphs = glyphs,
1180 designsize = designsize,
1181 header = header,
1182 fonts = fonts,
1183 }
1184 end
1185 end
1186
1187
1188
1189 function readers.loadtfmvf(tfmname,size)
1190 local vfname = file.addsuffix(file.nameonly(tfmfile),"vf")
1191 local tfmfile = tfmname
1192 local vffile = resolvers.findbinfile(vfname,"ovf")
1193 if tfmfile and tfmfile ~= "" then
1194 if size < 0 then
1195 size = idiv(65536 * -size,100)
1196 end
1197 local data = readers.loadtfm(tfmfile)
1198 if data.error then
1199 return data
1200 end
1201 if vffile and vffile ~= "" then
1202 data = readers.loadvf(vffile,data)
1203 if data.error then
1204 return data
1205 end
1206 end
1207 local designsize = data.designsize
1208 local glyphs = data.glyphs
1209 local parameters = data.parameters
1210 local fonts = data.fonts
1211 if size ~= designsize then
1212 local factor = size / designsize
1213 for index, glyph in next, glyphs do
1214 if next(glyph) then
1215 glyph.width = round(factor*glyph.width)
1216 glyph.height = round(factor*glyph.height)
1217 glyph.depth = round(factor*glyph.depth)
1218 local italic = glyph.italic
1219 if italic == 0 then
1220 glyph.italic = nil
1221 else
1222 glyph.italic = round(factor*glyph.italic)
1223 end
1224
1225 local kerns = glyph.kerns
1226 if kerns then
1227 for index, kern in next, kerns do
1228 kerns[index] = round(factor*kern)
1229 end
1230 end
1231
1232 local commands = glyph.commands
1233 if commands then
1234 for i=1,#commands do
1235 local c = commands[i]
1236 local t = c[1]
1237 if t == "down" or t == "right" then
1238 c[2] = round(factor*c[2])
1239 elseif t == "rule" then
1240 c[2] = round(factor*c[2])
1241 c[3] = round(factor*c[3])
1242 end
1243 end
1244 end
1245 else
1246 glyphs[index] = nil
1247 end
1248 end
1249 for i=2,30 do
1250 local p = parameters[i]
1251 if p then
1252 parameters[i] = round(factor*p)
1253 else
1254 break
1255 end
1256 end
1257 if fonts then
1258 for k, v in next, fonts do
1259 v.size = round(factor*v.size)
1260 end
1261 end
1262 else
1263 for index, glyph in next, glyphs do
1264 if next(glyph) then
1265 if glyph.italic == 0 then
1266 glyph.italic = nil
1267 end
1268 else
1269 glyphs[index] = nil
1270 end
1271 end
1272 end
1273
1274 parameters.slant = parameters[1]
1275 parameters.space = parameters[2]
1276 parameters.space_stretch = parameters[3]
1277 parameters.space_shrink = parameters[4]
1278 parameters.x_height = parameters[5]
1279 parameters.quad = parameters[6]
1280 parameters.extra_space = parameters[7]
1281
1282 for i=1,7 do
1283 parameters[i] = nil
1284 end
1285
1286 data.characters = glyphs
1287 data.glyphs = nil
1288 data.size = size
1289
1290 data.filename = tfmfile
1291 data.format = "unknown"
1292
1293 return data
1294 end
1295 end
1296
1297end
1298
1299
1300
1301
1302
1303
1304
1305 |