]> git.donarmstrong.com Git - lilypond.git/blob - ttftool/ps.c
add dir
[lilypond.git] / ttftool / ps.c
1 /* Copyright (c) 1997-1998 by Juliusz Chroboczek */
2
3 #include <sys/types.h>
4 #include <stdio.h>
5 #include <unistd.h>
6 #include <malloc.h>
7 #include "types.h"
8 #include "proto.h"
9
10 #define CHUNKSIZE 65534
11
12 #define NAMEOF(i) \
13         ((i)==0?\
14          ".notdef":\
15          ((postType==2)?\
16           ((gnt[i].type==0)?\
17            (gnt[i].name.index==0?NULL:macGlyphEncoding[gnt[i].name.index]):\
18            gnt[i].name.name):\
19           ((i)<258?macGlyphEncoding[i]:NULL)))
20
21
22 void
23 printPSFont (FILE * out, struct HeadTable *ht,
24              char **strings, int nglyphs, int postType,
25              struct PostTable *pt, struct GlyphName *gnt, int fd)
26 {
27   printPSHeader (out, ht, strings, pt);
28   printPSData (out, fd);
29   printPSTrailer (out, nglyphs, postType, gnt);
30 }
31
32 void
33 printPSHeader (FILE * out, struct HeadTable *ht,
34                char **strings, struct PostTable *pt)
35 {
36   fprintf (out, "%%!PS-TrueTypeFont\n");
37   if (pt->maxMemType42)
38     fprintf (out, "%%%%VMUsage: %ld %ld\n", pt->minMemType42,
39              pt->maxMemType42);
40   fprintf (out, "%d dict begin\n", 11);
41   fprintf (out, "/FontName /%s def\n", strings[6] ? strings[6] : "Unknown");
42   fprintf (out, "/Encoding StandardEncoding def\n");
43   fprintf (out, "/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n");
44   fprintf (out, "/FontBBox [%ld %ld %ld %ld] def\n",
45            ht->xMin * 1000L / ht->unitsPerEm,
46            ht->yMin * 1000L / ht->unitsPerEm,
47            ht->xMax * 1000L / ht->unitsPerEm,
48            ht->yMax * 1000L / ht->unitsPerEm);
49   fprintf (out, "/FontType 42 def\n");
50   fprintf (out, "/FontInfo 8 dict dup begin\n");
51   fprintf (out, "/version (%d.%d) def\n",
52            ht->fontRevision.mantissa, ht->fontRevision.fraction);
53   if (strings[0])
54     {
55       fprintf (out, "/Notice (");
56       fputpss (strings[0], out);
57       fprintf (out, ") def\n");
58     }
59   if (strings[4])
60     {
61       fprintf (out, "/FullName (");
62       fputpss (strings[4], out);
63       fprintf (out, ") def\n");
64     }
65   if (strings[1])
66     {
67       fprintf (out, "/FamilyName (");
68       fputpss (strings[1], out);
69       fprintf (out, ") def\n");
70     }
71   fprintf (out, "/isFixedPitch %s def\n",
72            pt->isFixedPitch ? "true" : "false");
73   fprintf (out, "/UnderlinePosition %ld def\n",
74            pt->underlinePosition * 1000L / ht->unitsPerEm);
75   fprintf (out, "/UnderlineThickness %ld def\n",
76            pt->underlineThickness * 1000L / ht->unitsPerEm);
77   fprintf (out, "end readonly def\n");
78 }
79
80 void
81 printPSData (FILE * out, int fd)
82 {
83   static char xdigits[] = "0123456789ABCDEF";
84
85   unsigned char *buffer;
86   int i, j;
87
88   surely_lseek (fd, 0, SEEK_SET);
89
90   buffer = mymalloc (CHUNKSIZE);
91
92   fprintf (out, "/sfnts [");
93   for (;;)
94     {
95       i = read (fd, buffer, CHUNKSIZE);
96       if (i == 0)
97         break;
98       fprintf (out, "\n<");
99       for (j = 0; j < i; j++)
100         {
101           if (j != 0 && j % 36 == 0)
102             putc ('\n', out);
103           /* fprintf(out,"%02X",(int)buffer[j]) is too slow */
104           putc (xdigits[(buffer[j] & 0xF0) >> 4], out);
105           putc (xdigits[buffer[j] & 0x0F], out);
106         }
107       fprintf (out, "00>");     /* Adobe bug? */
108       if (i < CHUNKSIZE)
109         break;
110     }
111   fprintf (out, "\n] def\n");
112   free (buffer);
113 }
114
115 void
116 printPSTrailer (FILE * out, int nglyphs, int postType, struct GlyphName *gnt)
117 {
118   int i, n;
119   char *name;
120
121   fprintf (out, "/CharStrings %d dict dup begin\n", nglyphs);
122   switch (postType)
123     {
124     case 2:
125       for (n = i = 0; i < nglyphs; i++)
126         {
127           if (n != 0 && n % 4 == 0)
128             fprintf (out, "\n");
129           name = NAMEOF (i);
130           if (name)
131             {
132               fprintf (out, "/%s %d def ", name, i);
133               n++;
134             }
135         }
136       break;
137     default:
138       if (postType != 1)
139         {
140           if (verbosity > -2)
141             fprintf (stderr,
142                      "No glyph name table; assuming MacGlyphEncoding\n");
143         }
144       for (i = 0; i < 258 && i < nglyphs; i++)
145         {
146           fprintf (out, "/%s %d def ", macGlyphEncoding[i], i);
147           if (i != 0 && i % 4 == 0)
148             fprintf (out, "\n");
149         }
150       break;
151     }
152   fprintf (out, "end readonly def\n");
153   fprintf (out, "FontName currentdict end definefont pop\n");
154 }
155
156 void
157 printAFM (FILE * afm, struct HeadTable *ht,
158           char **strings, int nglyphs, int postType,
159           struct PostTable *pt, struct GlyphName *gnt,
160           struct Box *bbox, struct HheaTable *hhea, longHorMetric * hmtx,
161           int nkern, int *nke, struct KernEntry0 **ke)
162 {
163   fprintf (afm, "StartFontMetrics 3.0\n");
164   fprintf (afm, "Comment Automatically generated by ttfps -- do not edit\n");
165   printAFMHeader (afm, ht, strings, pt);
166   printAFMMetrics (afm, ht, nglyphs, postType, gnt, bbox, hhea, hmtx);
167   printAFMKerning (afm, ht, postType, gnt, nkern, nke, ke);
168   fprintf (afm, "EndFontMetrics\n");
169 }
170
171 void
172 printAFMHeader (FILE * afm, struct HeadTable *ht,
173                 char **strings, struct PostTable *pt)
174 {
175   fprintf (afm, "FontName %s\n", strings[6] ? strings[6] : "Unknown");
176   if (strings[4])
177     fprintf (afm, "FullName %s\n", strings[4]);
178   if (strings[1])
179     fprintf (afm, "FamilyName %s\n", strings[1]);
180   fprintf (afm, "IsFixedPitch %s\n", pt->isFixedPitch ? "true" : "false");
181   fprintf (afm, "FontBBox %ld %ld %ld %ld\n",
182            ht->xMin * 1000L / ht->unitsPerEm,
183            ht->yMin * 1000L / ht->unitsPerEm,
184            ht->xMax * 1000L / ht->unitsPerEm,
185            ht->yMax * 1000L / ht->unitsPerEm);
186   fprintf (afm, "UnderlinePosition %ld\n",
187            pt->underlinePosition * 1000L / ht->unitsPerEm);
188   fprintf (afm, "UnderlineThickness %ld\n",
189            pt->underlineThickness * 1000L / ht->unitsPerEm);
190   fprintf (afm, "Version %d.%u\n", ht->fontRevision.mantissa,
191            ht->fontRevision.fraction);
192   if (strings[0])
193     fprintf (afm, "Notice %s\n", strings[0]);
194   fprintf (afm, "EncodingScheme AdobeStandardEncoding\n");
195   /*  fprintf(afm,"CapHeight %d\n");
196      fprintf(afm,"XHeight %d\n");
197      fprintf(afm,"Ascender %d\n");
198      fprintf(afm,"Descender %d\n");  */
199 }
200
201 void
202 printAFMMetrics (FILE * afm, struct HeadTable *ht,
203                  int nglyphs, int postType, struct GlyphName *gnt,
204                  struct Box *bbox,
205                  struct HheaTable *hhea, longHorMetric * hmtx)
206 {
207   int i, j;
208   char *name;
209   struct hashtable *table;
210   char *already_done;
211
212   /* Hash all the character names */
213   table = make_hashtable (nglyphs / 3 + 1);
214   for (i = 0; i < nglyphs; i++)
215     {
216       name = NAMEOF (i);
217       if (name)
218         puthash (table, name, i);
219     }
220
221   already_done = mycalloc (nglyphs, sizeof (char));
222
223   fprintf (afm, "StartCharMetrics %d\n", nglyphs);
224   /* First, print out the encoded glyphs */
225   for (i = 0; i < 256; i++)
226     {
227       if (adobeStandardEncoding[i])
228         {
229           j = gethash (table, adobeStandardEncoding[i]);
230           if (j >= 0)
231             {
232               printOneAFMMetric (afm, j, i, adobeStandardEncoding[i],
233                                  ht, bbox, hhea, hmtx);
234               already_done[j] = 1;
235             }
236         }
237     }
238   /* Now, print out the others */
239   for (j = 0; j < nglyphs; j++)
240     {
241       if (!already_done[j])
242         {
243           name = NAMEOF (j);
244           printOneAFMMetric (afm, j, -1, name, ht, bbox, hhea, hmtx);
245         }
246     }
247   fprintf (afm, "EndCharMetrics\n");
248 }
249
250 void
251 printOneAFMMetric (FILE * afm,
252                    int index, int code, char *name,
253                    struct HeadTable *ht,
254                    struct Box *bbox,
255                    struct HheaTable *hhea, longHorMetric * hmtx)
256 {
257   if (name)
258     {
259       fprintf (afm, "C %d ;", code);
260       if (hhea && hmtx)
261         fprintf (afm, " WX %ld ;",
262                  index < hhea->numberOfHMetrics ?
263                  hmtx[index].advanceWidth * 1000L / ht->unitsPerEm :
264                  hmtx[hhea->numberOfHMetrics -
265                       1].advanceWidth * 1000L / ht->unitsPerEm);
266       fprintf (afm, " N %s ;", name);
267       if (bbox)
268         fprintf (afm, " B %ld %ld %ld %ld ;",
269                  bbox[index].xMin * 1000L / ht->unitsPerEm,
270                  bbox[index].yMin * 1000L / ht->unitsPerEm,
271                  bbox[index].xMax * 1000L / ht->unitsPerEm,
272                  bbox[index].yMax * 1000L / ht->unitsPerEm);
273       fprintf (afm, "\n");
274     }
275 }
276
277 void
278 printAFMKerning (FILE * afm, struct HeadTable *ht,
279                  int postType, struct GlyphName *gnt,
280                  int nkern, int *nke, struct KernEntry0 **ke)
281 {
282   int i, j, n;
283
284   for (n = i = 0; i < nkern; i++)
285     n += nke[i];
286   if (n == 0)
287     return;
288
289   fprintf (afm, "StartKernData\nStartKernPairs %d\n", n);
290
291   for (i = 0; i < nkern; i++)
292     for (j = 0; j < nke[i]; j++)
293       fprintf (afm, "KPX %s %s %ld\n",
294                NAMEOF (ke[i][j].left),
295                NAMEOF (ke[i][j].right),
296                ke[i][j].value * 1000L / ht->unitsPerEm);
297   fprintf (afm, "EndKernPairs\nEndKernData\n");
298 }