1#!/bin/sh
2
3if [ $# -ne 1 ]; then
4  echo "usage: $0 font-name | gsnd -q - >font-name.afm" >&2
5  exit 1
6fi
7
8cat << EOF
9%!
10% produce .afm for $1
11% (c) 1993 by Robert Joop <rj@rainbow.in-berlin.de>
12% inspired by two other versions of this theme which are
13%	getafm 1.00 (c) AJCD
14% and getafm.ps by an unknown author,
15%	modified by J. Daniel Smith <dsmith@mailhost.aa.cad.slb.com>
16%
17% modified by Joachim H. Kaiser <jhk@cmpnetmail.com>:
18% - suggest a quiet gs run in usage
19% - get font version info (from 'version', not 'Version')
20% - add copyright field to output
21
22% Metrics dictionary code added by AJCD, 7/6/93
23
24/getafmdict 100 dict dup begin
25
26  /buf 256 string def
27  /buf2 16 string def
28
29  /prany	% dict dictname printname -> dict
30  {
31    2 index 2 index cvn known
32    {
33      print % printname
34      ( ) print
35      1 index exch cvn get =
36    }
37    {
38      (Comment /FontInfo contains no /) print
39      2 copy eq
40      {
41        = % printname
42	pop % dictname
43      }
44      {
45	exch
46	print % dictname
47	(, therefore no ) print
48	= % printname
49      }
50      ifelse
51    }
52    ifelse
53  }
54  bind def
55
56  /printfontname
57  {
58    (FontName)dup prany
59  }
60  bind def
61
62  /printfontinfo
63  {
64    dup /FontInfo known
65    {
66      dup /FontInfo get
67	(FullName)dup prany
68	(FamilyName)dup prany
69	(Weight)dup prany
70	(ItalicAngle)dup prany
71	(isFixedPitch)(IsFixedPitch) prany
72	(UnderlinePosition)dup prany
73	(UnderlineThickness)dup prany
74	(version)(Version) prany
75	(Notice)dup prany
76	(Copyright)dup prany
77      pop
78    }
79    {
80      (Comment Font lacks a /FontInfo!)=
81    }
82    ifelse
83  }
84  bind def
85
86  /prbbox % llx lly urx ury -> -
87  {
88    4 1 roll 3 1 roll exch % swap top 4 elements
89    4 { ( ) print buf cvs print } repeat
90  }
91  bind def
92
93  /getbbox % fontdict chardict character -> fontdict chardict llx lly urx ury
94  {
95    gsave
96      2 index setfont 0 0 moveto
97      false charpath flattenpath pathbbox
98    grestore
99  }
100  bind def
101
102  /printmiscinfo
103  {
104    dup /FontBBox known
105    {
106      (FontBBox) print
107      dup /FontBBox get aload pop prbbox ()=
108    }
109    {
110      (Comment missing required /FontBBox)=
111      quit
112    }
113    ifelse
114    2 copy exch get
115      dup /H known
116      1 index /x known and
117      1 index /d known and
118      1 index /p known and
119      dup /looksRoman exch def
120      {
121	(CapHeight ) print
122	(H) getbbox
123	ceiling cvi = pop pop pop
124	(XHeight ) print
125	(x) getbbox
126	ceiling cvi = pop pop pop
127	(Ascender ) print
128	(d) getbbox
129	ceiling cvi = pop pop pop
130	(Descender ) print
131	(p) getbbox
132	pop pop floor cvi = pop
133      }
134      {
135	(Comment font doesn't contain H, x, d and p; therefore no CapHeight, XHeight, Ascender and Descender)=
136      }
137      ifelse
138    pop
139    dup /Encoding get
140      [
141	[ (ISOLatin1Encoding) /ISOLatin1Encoding ]
142	[ (AdobeStandardEncoding) /StandardEncoding ]
143      ]
144      {
145	aload pop dup where
146	{
147	  exch get 2 index eq
148	  {
149	    (EncodingScheme ) print
150	    buf cvs =
151	  }
152	  {
153	    pop
154	  }
155	  ifelse
156	}
157	{
158	  pop pop
159	}
160	ifelse
161      }
162      forall
163    pop
164  }
165  bind def
166
167  /printcharmetric
168  {
169    % chardictname fontdict charnamedict encoding charindex charname
170
171    4 index dup length dict dup begin exch
172      {
173	1 index /FID ne
174	2 index /UniqueID ne
175	and
176	{
177	  1 index /Encoding eq { 256 array copy } if
178	  def
179	}
180	{ pop pop }
181	ifelse
182      }
183      forall
184    end
185    dup /Encoding get 32 3 index put
186    /f2 exch definefont
187    setfont
188
189    (C ) print
190    1 index buf cvs print
191
192    ( ; WX ) print
193% Metrics entries are:
194%       1 number:               which is the character width
195%       an array of 2 numbers:  which are the left sidebearing and width
196%       an array of 4 numbers:  x & y left sidebearing, width and height
197    dup 5 index         % /charname fontdict
198    dup /Metrics known {
199       /Metrics get exch 2 copy known {
200          get dup type /arraytype eq {
201             dup length 2 eq
202             {1 get} {2 get} ifelse
203          } if
204          round cvi buf cvs print
205       } {
206          pop pop ( ) stringwidth pop round cvi buf cvs print
207       } ifelse
208    } {
209       pop pop ( ) stringwidth pop round cvi buf cvs print
210    } ifelse
211
212    ( ; N ) print
213    dup buf cvs print
214
215    ( ; B) print
216    gsave
217      newpath 0 0 moveto
218      ( ) true charpath flattenpath pathbbox
219    grestore
220    2 { ceiling cvi 4 1 roll } repeat
221    2 { floor cvi 4 1 roll } repeat
222    prbbox
223
224    looksRoman
225    {
226      [
227	[ /f [ /i /f /l ] ]
228	[ /ff [ /i /l ] ]
229      ]
230      {
231	aload pop 1 index 3 index eq
232	{
233	  { 
234	    1 index buf cvs
235	    length
236	    1 index buf2 cvs dup length
237	    2 index add
238	    buf
239	    4 2 roll putinterval
240	    buf 0
241	    3 -1 roll getinterval
242	    dup cvn
243	    7 index
244	    exch known
245	    {
246	      exch
247	      ( ; L ) print
248	      buf2 cvs print
249	      ( ) print
250	      print
251	    }
252	    {
253	      pop pop
254	    }
255	    ifelse
256	  }
257	  forall
258	  pop 
259	}
260	{
261	  pop pop
262	}
263	ifelse
264      }
265      forall
266    }
267    if
268    pop
269
270    ( ;)=
271  }
272  bind def
273
274  /printcharmetrics
275  {
276    (StartCharMetrics ) print
277    2 copy exch get length 1 sub buf cvs =
278
279    256 dict dup begin
280      1 index /Encoding get
281      { null def }
282      forall
283    end
284    % chardictname fontdict charnamedict
285    1 index /Encoding get
286    0 1 255
287    {
288      % encoding index
289      2 copy get
290      dup /.notdef eq { pop } { printcharmetric } ifelse
291      pop % index
292    } for
293
294    -1
295    3 index 5 index get
296    {
297      pop
298      dup /.notdef eq
299      { pop }
300      {
301	% chardictname fontdict charnamedict encoding charindex charname
302	dup 4 index exch known
303	{ pop }
304	{ printcharmetric }
305	ifelse
306      }
307      ifelse
308    }
309    forall
310    % charnamedict encoding index
311    pop pop pop
312
313    (EndCharMetrics)=
314  }
315  bind def
316
317  /printfontmetrics
318  {
319    (StartFontMetrics 3.0)=
320    (Comment Produced by getafm 3.0 (which is by rj@rainbow.in-berlin.de))=
321
322    printfontname
323    printfontinfo
324    printmiscinfo
325    printcharmetrics
326
327    (EndFontMetrics)=
328  }
329  bind def
330
331end def
332
333/getafm
334{
335  getafmdict begin
336    save exch
337      findfont 1000 scalefont 
338
339      null
340      [ /CharDefs /CharData /CharProcs /CharStrings ]
341      {
342	2 index 1 index known { exch } if
343	pop
344      }
345      forall
346      dup null eq
347      {
348	(can't find dictionary with character data!)=
349	quit
350      }
351      if
352      exch % dictname fontdict
353
354      printfontmetrics
355
356      pop pop
357    restore
358  end
359}
360bind def
361
362/$1 getafm
363
364EOF
365