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 = readinteger1(s)
360 yoffset = readinteger1(s)
361 elseif c >= 4 and c <= 6 then
362 length = band(flagbyte,3) * 65536 + readcardinal1(s) * 256 + readcardinal1(s) - 4
363 index = readcardinal1(s)
364 width = readinteger3(s)
365 pixels = readcardinal2(s)
366 xsize = readcardinal2(s)
367 ysize = readcardinal2(s)
368 xoffset = readinteger2(s)
369 yoffset = readinteger2(s)
370 else
371 length = readcardinal4(s) - 9
372 index = readcardinal4(s)
373 width = readinteger4(s)
374 pixels = readcardinal4(s)
375 readcardinal4(s)
376 xsize = readcardinal4(s)
377 ysize = readcardinal4(s)
378 xoffset = readinteger4(s)
379 yoffset = readinteger4(s)
380 end
381 local glyph = {
382 index = index,
383 width = width,
384 pixels = pixels,
385 xsize = xsize,
386 ysize = ysize,
387 xoffset = xoffset,
388 yoffset = yoffset,
389 }
390 if length <= 0 then
391 data.error = "bad packet"
392 return data
393 end
394 readbitmap(glyph,s,flagbyte)
395 glyphs[index] = glyph
396 elseif flagbyte == 240 then
397
398 skipbytes(s,readcardinal1(s))
399 elseif flagbyte == 241 then
400
401 skipbytes(s,readcardinal2(s)*2)
402 elseif flagbyte == 242 then
403
404 skipbytes(s,readcardinal3(s)*3)
405 elseif flagbyte == 243 then
406
407 skipbytes(s,readcardinal4(s)*4)
408 elseif flagbyte == 244 then
409
410 skipbytes(s,4)
411 elseif flagbyte == 245 then
412 break
413 elseif flagbyte == 246 then
414
415 else
416 data.error = "unknown pk command"
417 break
418 end
419 end
420 return data
421 end
422
423end
424
425do
426
427 local leftboundary = -1
428 local rightboundary = -2
429 local boundarychar = 65536
430
431 function readers.loadtfm(filename)
432 local data
433
434 local function someerror(m)
435 if not data then
436 data = { }
437 end
438 data.error = m or "fatal error"
439 return data
440 end
441
442 local s = openstream(filename)
443 if not s then
444 return someerror()
445 end
446
447 local wide = false
448 local header = 0
449 local max = 0
450 local size = streamsize(s)
451 local glyphs = table.setmetatableindex(function(t,k)
452 local v = {
453
454 width = 0,
455 height = 0,
456 depth = 0,
457 italic = 0,
458 }
459 t[k] = v
460 return v
461 end)
462 local parameters = { }
463 local direction = 0
464
465 local lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np
466
467 lf = readcardinal2(s)
468 if lf ~= 0 then
469 header = 6
470 max = 255
471 wide = false
472 lh = readcardinal2(s)
473 bc = readcardinal2(s)
474 ec = readcardinal2(s)
475 nw = readcardinal2(s)
476 nh = readcardinal2(s)
477 nd = readcardinal2(s)
478 ni = readcardinal2(s)
479 nl = readcardinal2(s)
480 nk = readcardinal2(s)
481 ne = readcardinal2(s)
482 np = readcardinal2(s)
483 else
484 header = 14
485 max = 65535
486 wide = readcardinal4(s) == 0
487 if not wide then
488 return someerror("invalid format")
489 end
490 lf = readcardinal4(s)
491 lh = readcardinal4(s)
492 bc = readcardinal4(s)
493 ec = readcardinal4(s)
494 nw = readcardinal4(s)
495 nh = readcardinal4(s)
496 nd = readcardinal4(s)
497 ni = readcardinal4(s)
498 nl = readcardinal4(s)
499 nk = readcardinal4(s)
500 ne = readcardinal4(s)
501 np = readcardinal4(s)
502 direction = readcardinal4(s)
503 end
504 if (bc > ec + 1) or (ec > max) then
505 return someerror("file is too small")
506 end
507 if bc > max then
508 bc, ec = 1, 0
509 end
510 local nlw = (wide and 2 or 1) * nl
511 local neew = (wide and 2 or 1) * ne
512 local ncw = (wide and 2 or 1) * (ec - bc + 1)
513 if lf ~= (header + lh + ncw + nw + nh + nd + ni + nlw + nk + neew + np) then
514 return someerror("file is too small")
515 end
516 if nw == 0 or nh == 0 or nd == 0 or ni == 0 then
517 return someerror("no glyphs")
518 end
519 if lf * 4 > size then
520 return someerror("file is too small")
521 end
522 local slh = lh
523 if lh < 2 then
524 return someerror("file is too small")
525 end
526 local checksum = readcardinal4(s)
527 local designsize = readcardinal2(s)
528 designsize = designsize * 256 + readcardinal1(s)
529 designsize = designsize * 16 + rshift(readcardinal1(s),4)
530 if designsize < 0xFFFF then
531 return someerror("weird designsize")
532 end
533
534 local alpha = 16
535 local z = designsize
536 while z >= 040000000 do
537 z = rshift(z,1)
538 alpha = alpha + alpha
539 end
540 local beta = idiv(256,alpha)
541 alpha = alpha * z
542
543 local function readscaled()
544 local a, b, c, d = readbytes(s,4)
545 local n = idiv(rshift(rshift(d*z,8)+c*z,8)+b*z,beta)
546 if a == 0 then
547 return n
548 elseif a == 255 then
549 return n - alpha
550 else
551 return 0
552 end
553 end
554
555 local function readunscaled()
556 local a, b, c, d = readbytes(s,4)
557 if a > 127 then
558 a = a - 256
559 end
560 return a * 0xFFFFF + b * 0xFFF + c * 0xF + rshift(d,4)
561 end
562
563 while lh > 2 do
564 skipbytes(s,4)
565 lh = lh - 1
566 end
567 local saved = getposition(s)
568 setposition(s,(header + slh + ncw) * 4 + 1)
569 local widths = { } for i=0,nw-1 do widths [i] = readscaled() end
570 local heights = { } for i=0,nh-1 do heights[i] = readscaled() end
571 local depths = { } for i=0,nd-1 do depths [i] = readscaled() end
572 local italics = { } for i=0,ni-1 do italics[i] = readscaled() end
573 if widths[0] ~= 0 or heights[0] ~= 0 or depths[0] ~= 0 then
574 return someerror("invalid dimensions")
575 end
576
577 local blabel = nl
578 local bchar = boundarychar
579
580 local ligatures = { }
581 if nl > 0 then
582 for i=0,nl-1 do
583 local a, b, c, d = readbytes(s,4)
584 ligatures[i] = {
585 skip = a,
586 nxt = b,
587 op = c,
588 rem = d,
589 }
590 if a > 128 then
591 if 256 * c + d >= nl then
592 return someerror("invalid ligature table")
593 end
594 if a == 255 and i == 0 then
595 bchar = b
596 end
597 else
598 if c < 128 then
599
600 elseif 256 * (c - 128) + d >= nk then
601 return someerror("invalid ligature table")
602 end
603 if (a < 128) and (i - 0 + a + 1 >= nl) then
604 return someerror("invalid ligature table")
605 end
606 end
607 if a == 255 then
608 blabel = 256 * c + d
609 end
610 end
611 end
612 local allkerns = { }
613 for i=0,nk-1 do
614 allkerns[i] = readscaled()
615 end
616 local extensibles = { }
617 for i=0,ne-1 do
618 extensibles[i] = wide and {
619 top = readcardinal2(s),
620 bot = readcardinal2(s),
621 mid = readcardinal2(s),
622 rep = readcardinal2(s),
623 } or {
624 top = readcardinal1(s),
625 bot = readcardinal1(s),
626 mid = readcardinal1(s),
627 rep = readcardinal1(s),
628 }
629 end
630 for i=1,np do
631 if i == 1 then
632 parameters[i] = readunscaled()
633 else
634 parameters[i] = readscaled()
635 end
636 end
637 for i=1,7 do
638 if not parameters[i] then
639 parameters[i] = 0
640 end
641 end
642
643 setposition(s,saved)
644 local extras = false
645 if blabel ~= nl then
646 local k = blabel
647 while true do
648 local l = ligatures[k]
649 local skip = l.skip
650 if skip <= 128 then
651
652
653
654 extras = true
655
656 end
657 if skip == 0 then
658 k = k + 1
659 else
660 if skip >= 128 then
661 break
662 end
663 k = k + skip + 1
664 end
665 end
666 end
667 if extras then
668 local ligas = { }
669 local kerns = { }
670 local k = blabel
671 while true do
672 local l = ligatures[k]
673 local skip = l.skip
674 if skip <= 128 then
675 local nxt = l.nxt
676 local op = l.op
677 local rem = l.rem
678 if op >= 128 then
679 kerns[nxt] = allkerns[256 * (op - 128) + rem]
680 else
681 ligas[nxt] = { type = op * 2 + 1, char = rem }
682 end
683 end
684 if skip == 0 then
685 k = k + 1
686 else
687 if skip >= 128 then
688 break;
689 end
690 k = k + skip + 1
691 end
692 end
693 if next(kerns) then
694 local glyph = glyphs[leftboundary]
695 glyph.kerns = kerns
696 glyph.remainder = 0
697 end
698 if next(ligas) then
699 local glyph = glyphs[leftboundary]
700 glyph.ligatures = ligas
701 glyph.remainder = 0
702 end
703 end
704 for i=bc,ec do
705 local glyph, width, height, depth, italic, tag, remainder
706 if wide then
707 width = readcardinal2(s)
708 height = readcardinal1(s)
709 depth = readcardinal1(s)
710 italic = readcardinal1(s)
711 tag = readcardinal1(s)
712 remainder = readcardinal2(s)
713 else
714 width = readcardinal1(s)
715 height = readcardinal1(s)
716 depth = extract(height,0,4)
717 height = extract(height,4,4)
718 italic = readcardinal1(s)
719 tag = extract(italic,0,2)
720 italic = extract(italic,2,6)
721 remainder = readcardinal1(s)
722 end
723 if width == 0 then
724
725 else
726 if width >= nw or height >= nh or depth >= nd or italic >= ni then
727 return someerror("invalid dimension index")
728 end
729 local extensible, nextinsize
730 if tag == 0 then
731
732 else
733 local r = remainder
734 if tag == 1 then
735 if r >= nl then
736 return someerror("invalid ligature index")
737 end
738 elseif tag == 2 then
739 if r < bc or r > ec then
740 return someerror("invalid chain index")
741 end
742 while r < i do
743 local g = glyphs[r]
744 if g.tag ~= list_tag then
745 break
746 end
747 r = g.remainder
748 end
749 if r == i then
750 return someerror("cycles in chain")
751 end
752 nextinsize = r
753 elseif tag == 3 then
754 if r >= ne then
755 return someerror("bad extensible")
756 end
757 extensible = extensibles[r]
758 remainder = 0
759 end
760 end
761 glyphs[i] = {
762 width = widths [width],
763 height = heights[height],
764 depth = depths [depth],
765 italic = italics[italic],
766 tag = tag,
767
768 remainder = remainder,
769 extensible = extensible,
770 next = nextinsize,
771 }
772 end
773 end
774 for i=bc,ec do
775 local glyph = glyphs[i]
776 if glyph.tag == 1 then
777
778 local k = glyph.remainder
779 local l = ligatures[k]
780 if l.skip > 128 then
781 k = 256 * l.op + l.rem
782 end
783 local ligas = { }
784 local kerns = { }
785 while true do
786 local l = ligatures[k]
787 local skip = l.skip
788 if skip <= 128 then
789 local nxt = l.nxt
790 local op = l.op
791 local rem = l.rem
792 if op >= 128 then
793 local kern = allkerns[256 * (op - 128) + rem]
794 if nxt == bchar then
795 kerns[rightboundary] = kern
796 end
797 kerns[nxt] = kern
798 else
799 local ligature = { type = op * 2 + 1, char = rem }
800 if nxt == bchar then
801 ligas[rightboundary] = ligature
802 end
803 ligas[nxt] = ligature
804 end
805 end
806 if skip == 0 then
807 k = k + 1
808 else
809 if skip >= 128 then
810 break
811 end
812 k = k + skip + 1
813 end
814 end
815 if next(kerns)then
816 glyph.kerns = kerns
817 glyph.remainder = 0
818 end
819 if next(ligas) then
820 glyph.ligatures = ligas
821 glyph.remainder = 0
822 end
823 end
824 end
825
826 if bchar ~= boundarychar then
827 glyphs[rightboundary] = copy(glyphs[bchar])
828 end
829
830
831
832
833
834
835 return {
836 name = file.nameonly(filename),
837 fontarea = file.pathpart(filename),
838 glyphs = glyphs,
839 parameters = parameters,
840 designsize = designsize,
841 size = designsize,
842 direction = direction,
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858 }
859 end
860
861end
862
863do
864
865 local push = { "push" }
866 local push = { "pop" }
867
868 local w, x, y, z, f
869 local stack
870 local s, result, r
871 local alpha, beta, z
872
873 local function scaled1()
874 local a = readbytes(s,1)
875 if a == 0 then
876 return 0
877 elseif a == 255 then
878 return - alpha
879 else
880 return 0
881 end
882 end
883
884 local function scaled2()
885 local a, b = readbytes(s,2)
886 local sw = idiv(b*z,beta)
887 if a == 0 then
888 return sw
889 elseif a == 255 then
890 return sw - alpha
891 else
892 return 0
893 end
894 end
895
896 local function scaled3()
897 local a, b, c = readbytes(s,3)
898 local sw = idiv(rshift(c*z,8)+b*z,beta)
899 if a == 0 then
900 return sw
901 elseif a == 255 then
902 return sw - alpha
903 else
904 return 0
905 end
906 end
907
908 local function scaled4()
909 local a, b, c, d = readbytes(s,4)
910 local sw = idiv( rshift(rshift(d*z,8)+(c*z),8)+b*z,beta)
911 if a == 0 then
912 return sw
913 elseif a == 255 then
914 return sw - alpha
915 else
916 return 0
917 end
918 end
919
920 local function dummy()
921 end
922
923 local actions = {
924
925 [128] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) } p = p + 1 end,
926 [129] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) } p = p + 2 end,
927 [130] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal3(s) } p = p + 3 end,
928 [131] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) } p = p + 4 end,
929
930 [132] = function()
931 r = r + 1
932 result[r] = { "rule", scaled4(), scaled4() }
933 p = p + 8
934 end,
935
936 [133] = function()
937 r = r + 1 result[r] = push
938 r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) }
939 r = r + 1 result[r] = pop
940 p = p + 1
941 end,
942 [134] = function()
943 r = r + 1 result[r] = push
944 r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) }
945 r = r + 1 result[r] = pop
946 p = p + 2
947 end,
948 [135] = 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 + 3
953 end,
954 [136] = function()
955 r = r + 1 result[r] = push
956 r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) }
957 r = r + 1 result[r] = pop
958 p = p + 4
959 end,
960
961 [137] = function()
962 r = r + 1 result[r] = push
963 r = r + 1 result[r] = { "rule", scaled4(), scaled4() }
964 r = r + 1 result[r] = pop
965 p = p + 8
966 end,
967
968 [138] = dummy,
969 [139] = dummy,
970 [140] = dummy,
971
972 [141] = function()
973 insert(stack, { w, x, y, z })
974 r = r + 1
975 result[r] = push
976 end,
977 [142] = function()
978 local t = remove(stack)
979 if t then
980 w, x, y, z = t[1], t[2], t[3], t[4]
981 r = r + 1
982 result[r] = pop
983 end
984 end,
985
986 [143] = function() r = r + 1 result[r] = { "right", scaled1() } p = p + 1 end,
987 [144] = function() r = r + 1 result[r] = { "right", scaled2() } p = p + 2 end,
988 [145] = function() r = r + 1 result[r] = { "right", scaled3() } p = p + 3 end,
989 [146] = function() r = r + 1 result[r] = { "right", scaled4() } p = p + 4 end,
990
991 [148] = function() w = scaled1() r = r + 1 result[r] = { "right", w } p = p + 1 end,
992 [149] = function() w = scaled2() r = r + 1 result[r] = { "right", w } p = p + 2 end,
993 [150] = function() w = scaled3() r = r + 1 result[r] = { "right", w } p = p + 3 end,
994 [151] = function() w = scaled4() r = r + 1 result[r] = { "right", w } p = p + 4 end,
995
996 [153] = function() x = scaled1() r = r + 1 result[r] = { "right", x } p = p + 1 end,
997 [154] = function() x = scaled2() r = r + 1 result[r] = { "right", x } p = p + 2 end,
998 [155] = function() x = scaled3() r = r + 1 result[r] = { "right", x } p = p + 3 end,
999 [156] = function() x = scaled4() r = r + 1 result[r] = { "right", x } p = p + 4 end,
1000
1001 [157] = function() r = r + 1 result[r] = { "down", scaled1() } p = p + 1 end,
1002 [158] = function() r = r + 1 result[r] = { "down", scaled2() } p = p + 2 end,
1003 [159] = function() r = r + 1 result[r] = { "down", scaled3() } p = p + 3 end,
1004 [160] = function() r = r + 1 result[r] = { "down", scaled4() } p = p + 4 end,
1005
1006 [162] = function() y = scaled1() r = r + 1 result[r] = { "down", y } p = p + 1 end,
1007 [163] = function() y = scaled2() r = r + 1 result[r] = { "down", y } p = p + 2 end,
1008 [164] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 3 end,
1009 [165] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 4 end,
1010
1011 [167] = function() z = scaled1() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1012 [168] = function() z = scaled2() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1013 [169] = function() z = scaled3() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1014 [170] = function() z = scaled4() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
1015
1016 [147] = function() r = r + 1 result[r] = { "right", w } end,
1017 [152] = function() r = r + 1 result[r] = { "right", x } end,
1018 [161] = function() r = r + 1 result[r] = { "down", y } end,
1019 [166] = function() r = r + 1 result[r] = { "down", z } end,
1020
1021 [235] = function() f = readcardinal1(s) p = p + 1 end,
1022 [236] = function() f = readcardinal2(s) p = p + 3 end,
1023 [237] = function() f = readcardinal3(s) p = p + 3 end,
1024 [238] = function() f = readcardinal4(s) p = p + 4 end,
1025
1026 [239] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 1 + n end,
1027 [240] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 2 + n end,
1028 [241] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 3 + n end,
1029 [242] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 4 + n end,
1030
1031 [250] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 1 + n end,
1032 [251] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 2 + n end,
1033 [252] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 3 + n end,
1034 [253] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 4 + n end,
1035
1036 }
1037
1038 table.setmetatableindex(actions,function(t,cmd)
1039 local v
1040 if cmd >= 0 and cmd <= 127 then
1041 v = function()
1042 if f == 0 then
1043 f = 1
1044 end
1045 r = r + 1 ; result[r] = { "slot", f, cmd }
1046 end
1047 elseif cmd >= 171 and cmd <= 234 then
1048 cmd = cmd - 170
1049 v = function()
1050 r = r + 1 ; result[r] = { "font", cmd }
1051 end
1052 else
1053 v = dummy
1054 end
1055 t[cmd] = v
1056 return v
1057 end)
1058
1059 function readers.loadvf(filename,data)
1060
1061 local function someerror(m)
1062 if not data then
1063 data = { }
1064 end
1065 data.error = m or "fatal error"
1066 return data
1067 end
1068
1069 s = openstream(filename)
1070 if not s then
1071 return someerror()
1072 end
1073
1074 local cmd = readcardinal1(s)
1075 if cmd ~= 247 then
1076 return someerror("bad preamble")
1077 end
1078 cmd = readcardinal1(s)
1079 if cmd ~= 202 then
1080 return someerror("bad version")
1081 end
1082 local header = readstring(s,readcardinal1(s))
1083 local checksum = readcardinal4(s)
1084 local designsize = idiv(readcardinal4(s),16)
1085 local fonts = data and data.fonts or { }
1086 local glyphs = data and data.glyphs or { }
1087
1088 alpha = 16
1089 z = designsize
1090 while z >= 040000000 do
1091 z = rshift(z,1)
1092 alpha = alpha + alpha
1093 end
1094 beta = idiv(256,alpha)
1095 alpha = alpha * z
1096
1097 cmd = readcardinal1(s)
1098 while true do
1099 local n
1100 if cmd == 243 then
1101 n = readcardinal1(s) + 1
1102 elseif cmd == 244 then
1103 n = readcardinal2(s) + 1
1104 elseif cmd == 245 then
1105 n = readcardinal3(s) + 1
1106 elseif cmd == 246 then
1107 n = readcardinal4(s) + 1
1108 else
1109 break
1110 end
1111 local checksum = skipbytes(s,4)
1112 local size = scaled4()
1113 local designsize = idiv(readcardinal4(s),16)
1114 local pathlen = readcardinal1(s)
1115 local namelen = readcardinal1(s)
1116 local path = readstring(s,pathlen)
1117 local name = readstring(s,namelen)
1118 fonts[n] = { path = path, name = name, size = size }
1119 cmd = readcardinal1(s)
1120 end
1121 local index = 0
1122 while cmd and cmd <= 242 do
1123 local width = 0
1124 local length = 0
1125 local checksum = 0
1126 if cmd == 242 then
1127 length = readcardinal4(s)
1128 checksum = readcardinal4(s)
1129 width = readcardinal4(s)
1130 else
1131 length = cmd
1132 checksum = readcardinal1(s)
1133 width = readcardinal3(s)
1134 end
1135 w, x, y, z, f = 0, 0, 0, 0, false
1136 stack, result, r, p = { }, { }, 0, 0
1137 while p < length do
1138 local cmd = readcardinal1(s)
1139 p = p + 1
1140 actions[cmd]()
1141 end
1142 local glyph = glyphs[index]
1143 if glyph then
1144 glyph.width = width
1145 glyph.commands = result
1146 else
1147 glyphs[index] = {
1148 width = width,
1149 commands = result,
1150 }
1151 end
1152 index = index + 1
1153 if #stack > 0 then
1154
1155 end
1156 if packet_length ~= 0 then
1157
1158 end
1159 cmd = readcardinal1(s)
1160 end
1161 if readcardinal1(s) ~= 248 then
1162
1163 end
1164 s, result, r = nil, nil, nil
1165 if data then
1166 data.glyphs = data.glyphs or glyphs
1167 data.fonts = data.fonts or fonts
1168 return data
1169 else
1170 return {
1171 name = file.nameonly(filename),
1172 fontarea = file.pathpart(filename),
1173 glyphs = glyphs,
1174 designsize = designsize,
1175 header = header,
1176 fonts = fonts,
1177 }
1178 end
1179 end
1180
1181
1182
1183 function readers.loadtfmvf(tfmname,size)
1184 local vfname = file.addsuffix(file.nameonly(tfmfile),"vf")
1185 local tfmfile = tfmname
1186 local vffile = resolvers.findbinfile(vfname,"ovf")
1187 if tfmfile and tfmfile ~= "" then
1188 if size < 0 then
1189 size = idiv(65536 * -size,100)
1190 end
1191 local data = readers.loadtfm(tfmfile)
1192 if data.error then
1193 return data
1194 end
1195 if vffile and vffile ~= "" then
1196 data = readers.loadvf(vffile,data)
1197 if data.error then
1198 return data
1199 end
1200 end
1201 local designsize = data.designsize
1202 local glyphs = data.glyphs
1203 local parameters = data.parameters
1204 local fonts = data.fonts
1205 if size ~= designsize then
1206 local factor = size / designsize
1207 for index, glyph in next, glyphs do
1208 if next(glyph) then
1209 glyph.width = round(factor*glyph.width)
1210 glyph.height = round(factor*glyph.height)
1211 glyph.depth = round(factor*glyph.depth)
1212 local italic = glyph.italic
1213 if italic == 0 then
1214 glyph.italic = nil
1215 else
1216 glyph.italic = round(factor*glyph.italic)
1217 end
1218
1219 local kerns = glyph.kerns
1220 if kerns then
1221 for index, kern in next, kerns do
1222 kerns[index] = round(factor*kern)
1223 end
1224 end
1225
1226 local commands = glyph.commands
1227 if commands then
1228 for i=1,#commands do
1229 local c = commands[i]
1230 local t = c[1]
1231 if t == "down" or t == "right" then
1232 c[2] = round(factor*c[2])
1233 elseif t == "rule" then
1234 c[2] = round(factor*c[2])
1235 c[3] = round(factor*c[3])
1236 end
1237 end
1238 end
1239 else
1240 glyphs[index] = nil
1241 end
1242 end
1243 for i=2,30 do
1244 local p = parameters[i]
1245 if p then
1246 parameters[i] = round(factor*p)
1247 else
1248 break
1249 end
1250 end
1251 if fonts then
1252 for k, v in next, fonts do
1253 v.size = round(factor*v.size)
1254 end
1255 end
1256 else
1257 for index, glyph in next, glyphs do
1258 if next(glyph) then
1259 if glyph.italic == 0 then
1260 glyph.italic = nil
1261 end
1262 else
1263 glyphs[index] = nil
1264 end
1265 end
1266 end
1267
1268 parameters.slant = parameters[1]
1269 parameters.space = parameters[2]
1270 parameters.space_stretch = parameters[3]
1271 parameters.space_shrink = parameters[4]
1272 parameters.x_height = parameters[5]
1273 parameters.quad = parameters[6]
1274 parameters.extra_space = parameters[7]
1275
1276 for i=1,7 do
1277 parameters[i] = nil
1278 end
1279
1280 data.characters = glyphs
1281 data.glyphs = nil
1282 data.size = size
1283
1284 data.filename = tfmfile
1285 data.format = "unknown"
1286
1287 return data
1288 end
1289 end
1290
1291end
1292
1293
1294
1295
1296
1297
1298
1299 |