Build AFM data for core PostScript fonts into WINEPS.
[wine] / dlls / wineps / afm2c.c
1 /*******************************************************************************
2  *
3  *  Function to write WINEPS AFM data structures as C
4  *
5  *  Copyright 2001 Ian Pilcher
6  *
7  *
8  *  PSDRV_AFM2C(AFM *afm) writes the AFM data structure addressed by afm (and
9  *  its subsidiary objects) as a C file which can which can then be built in to
10  *  the driver.  It creates the file in the current directory with a name of
11  *  the form {FontName}.c, where {FontName} is the PostScript font name with
12  *  hyphens replaced by underscores.
13  *
14  *  To use this function, do the following:
15  *
16  *      *  Move this file to the dlls/wineps directory.
17  *
18  *      *  Edit dlls/wineps/Makefile (or dlls/wineps/Makefile.in) and add
19  *         afm2c.c as a source file.
20  *
21  *      *  Edit dlls/wineps/afm.c and uncomment the call to PSDRV_AFM2C in
22  *         CalcWindowsMetrics() (or wherever it gets moved).  The resulting
23  *         compiler warning can be safely ignored.
24  *
25  *  IMPORTANT:  For this to work, all glyph names in the AFM data being
26  *      written *MUST* already be present in PSDRV_AGLGlyphNames in agl.c.
27  *      See mkagl.c in this directory for information on how to generate
28  *      updated glyph name information.  Note, however, that if the glyph
29  *      name information in agl.c is regenerated, *ALL* AFM data must also
30  *      be recreated.
31  *
32  */
33
34 #include <string.h>
35 #include <stdio.h>
36 #include <math.h>
37
38 #include "debugtools.h"
39 #include "psdrv.h"
40
41 DEFAULT_DEBUG_CHANNEL(psdrv);
42
43 inline static void cursorto(FILE *of, int np, int cp)
44 {
45     int ntp = np & 0xfffffff8;
46     int ctp = cp & 0xfffffff8;
47     
48     while (ctp < ntp)
49     {
50         fputc('\t', of);
51         ctp += 8;
52         cp = ctp;
53     }
54     
55     while (cp < np)
56     {
57         fputc(' ', of);
58         ++cp;
59     }
60 }
61
62 static void writeCharWidths(FILE *of, AFM * afm)
63 {
64     int i, cp, w, row_start = 0;
65     
66     fputc('\t', of);  cp = 8;
67     
68     for (i = 0; i < 255; ++i)
69     {
70         if (afm->CharWidths[i] == 0.0)
71             w = 3;
72         else
73             w = (int)log10(afm->CharWidths[i]) + 3;
74             
75         if (cp + w < 40)
76         {
77             cp += fprintf(of, "%g, ", (double)(afm->CharWidths[i]));
78         }
79         else
80         {
81             cursorto(of, 40, cp);
82             fprintf(of, "/* CharWidths[%i] - CharWidths[%i] */\n\t",
83                     row_start, i - 1);
84             cp = 8;
85             row_start = i;
86             --i;
87         }
88     }
89     
90     if (afm->CharWidths[255] == 0.0)
91         w = 3;
92     else
93         w = (int)pow(afm->CharWidths[i], 0.1) + 3;
94         
95     if (cp + w < 40)
96     {
97         cp += fprintf(of, "%g", (double)(afm->CharWidths[255]));
98         cursorto(of, 40, cp);
99         fprintf(of, "/* CharWidths[%i] - CharWidths[255] */\n    },\n",
100                 row_start);
101     }
102     else
103     {
104         cursorto(of, 40, cp);
105         fprintf(of, "/* CharWidths[%i] - CharWidths[254] */\n\t", row_start);
106         cp = 8 + fprintf(of, "%g", (double)(afm->CharWidths[255]));
107         cursorto(of, 40, cp);
108         fputs("/* CharWidths[255] */\n    },\n", of);
109     }
110 }
111
112 static void writeHeader(FILE *of, AFM *afm, const char *buffer)
113 {
114     int i;
115     
116     fputc('/', of);
117     for (i = 1; i < 80; ++i)
118         fputc('*', of);
119     fprintf(of, "\n"
120                 " *\n"
121                 " *\tFont metric data for %s\n"
122                 " *\n"
123                 " *\tCopyright 2001 Ian Pilcher\n"
124                 " *\n"
125                 " *\n"
126                 " *\tThis data is derived from the Adobe Font Metrics files at"
127                         "\n"
128                 " *\n"
129                 " *\t    ftp://ftp.adobe.com/pub/adobe/type/win/all/afmfiles/"
130                         "base35/\n"
131                 " *\n"
132                 " *\twhich are Copyright 1985-1992 Adobe Systems Incorporated."
133                         "\n"
134                 " *\n"
135                 " */\n"
136                 "\n"
137                 "#include \"psdrv.h\"\n", afm->FullName);
138 }
139
140 static void writeEncoding(FILE *of, AFM *afm, const char *buffer)
141 {
142     int i;
143     
144     fprintf(of, "\n\n/*\n *  %s encoding vector\n */\n", afm->EncodingScheme);
145     
146     fprintf(of, "\nstatic const UNICODEGLYPH ug_%s[%i] =\n{\n", buffer,
147             afm->Encoding->size);
148             
149     for (i = 0; i < afm->Encoding->size - 1; ++i)
150     {
151         cursorto(of, 48,
152                 fprintf(of, "    { 0x%.4lx, PSDRV_AGLGlyphNames + %4i },",
153                 afm->Encoding->glyphs[i].UV,
154                 afm->Encoding->glyphs[i].name - PSDRV_AGLGlyphNames));
155         fprintf(of, "/* %s */\n", afm->Encoding->glyphs[i].name->sz);
156     }
157     
158     cursorto(of, 48, fprintf(of, "    { 0x%.4lx, PSDRV_AGLGlyphNames + %4i }",
159             afm->Encoding->glyphs[i].UV,
160             afm->Encoding->glyphs[i].name - PSDRV_AGLGlyphNames));
161     fprintf(of, "/* %s */\n};\n\n", afm->Encoding->glyphs[i].name->sz);
162     
163     fprintf(of, "static UNICODEVECTOR enc_%s = { %i, ug_%s };\n", buffer,
164             afm->Encoding->size, buffer);
165 }
166
167 static void writeMetrics(FILE *of, AFM *afm, const char *buffer)
168 {
169     int i;
170     
171     fputs("\n\n/*\n *  Glyph metrics\n */\n\n", of);
172     
173     fprintf(of, "static AFMMETRICS met_%s[%i] = \n{\n", buffer,
174             afm->NumofMetrics);
175             
176     for (i = 0; i < afm->NumofMetrics - 1; ++i)
177     {
178         fputs("    {\n\t", of);
179         fprintf(of, "%3i, 0x%.4lx, %4g, PSDRV_AGLGlyphNames + %4i,\n\t\t",
180                 afm->Metrics[i].C, afm->Metrics[i].UV, afm->Metrics[i].WX,
181                 afm->Metrics[i].N - PSDRV_AGLGlyphNames);
182         fprintf(of, "{ %4g, %4g, %4g, %4g }, NULL\t/* %s */\n    },\n",
183                 afm->Metrics[i].B.llx, afm->Metrics[i].B.lly,
184                 afm->Metrics[i].B.urx, afm->Metrics[i].B.ury,
185                 afm->Metrics[i].N->sz);
186     }
187     
188     fputs("    {\n\t", of);
189     fprintf(of, "%3i, 0x%.4lx, %4g, PSDRV_AGLGlyphNames + %4i,\n\t\t",
190             afm->Metrics[i].C, afm->Metrics[i].UV, afm->Metrics[i].WX,
191             afm->Metrics[i].N - PSDRV_AGLGlyphNames);
192     fprintf(of, "{ %4g, %4g, %4g, %4g }, NULL\t/* %s */\n    }\n};\n",
193             afm->Metrics[i].B.llx, afm->Metrics[i].B.lly,
194             afm->Metrics[i].B.urx, afm->Metrics[i].B.ury,
195             afm->Metrics[i].N->sz);
196 }
197
198 static void writeAFM(FILE *of, AFM *afm, const char *buffer)
199 {
200     fputs("\n\n/*\n *  Font metrics\n */\n\n", of);
201
202     fprintf(of, "AFM PSDRV_%s =\n{\n", buffer);
203     cursorto(of, 48, fprintf(of, "    \"%s\",", afm->FontName));
204     fputs("/* FontName */\n", of);
205     cursorto(of, 48, fprintf(of, "    \"%s\",", afm->FullName));
206     fputs("/* FullName */\n", of);
207     cursorto(of, 48, fprintf(of, "    \"%s\",", afm->FamilyName));
208     fputs("/* FamilyName */\n", of);
209     cursorto(of, 48, fprintf(of, "    \"%s\",", afm->EncodingScheme));
210     fputs("/* EncodingScheme */\n", of);
211     cursorto(of, 48, fprintf(of, "    %li,", afm->Weight));
212     fputs("/* Weight */\n", of);
213     cursorto(of, 48, fprintf(of, "    %g,", afm->ItalicAngle));
214     fputs("/* ItalicAngle */\n", of);
215     cursorto(of, 48, fprintf(of, "    %s,",
216             afm->IsFixedPitch ? "TRUE" : "FALSE"));
217     fputs("/* IsFixedPitch */\n", of);
218     cursorto(of, 48, fprintf(of, "    %g,", afm->UnderlinePosition));
219     fputs("/* UnderlinePosition */\n", of);
220     cursorto(of, 48, fprintf(of, "    %g,", afm->UnderlineThickness));
221     fputs("/* UnderlineThickness */\n", of);
222     cursorto(of, 48, fprintf(of, "    { %g, %g, %g, %g },", afm->FontBBox.llx,
223             afm->FontBBox.lly, afm->FontBBox.urx, afm->FontBBox.ury));
224     fputs("/* FontBBox */\n", of);
225     cursorto(of, 48, fprintf(of, "    %g,", afm->CapHeight));
226     fputs("/* CapHeight */\n", of);
227     cursorto(of, 48, fprintf(of, "    %g,", afm->XHeight));
228     fputs("/* XHeight */\n", of);
229     cursorto(of, 48, fprintf(of, "    %g,", afm->Ascender));
230     fputs("/* Ascender */\n", of);
231     cursorto(of, 48, fprintf(of, "    %g,", afm->Descender));
232     fputs("/* Descender */\n", of);
233     cursorto(of, 48, fprintf(of, "    %g,", afm->FullAscender));
234     fputs("/* FullAscender */\n", of);
235     fputs("    {\n", of);
236     cursorto(of, 40, 7 + fprintf(of, "\t%u,",
237             (unsigned int)(afm->WinMetrics.usUnitsPerEm)));
238     fputs("/* WinMetrics.usUnitsPerEm */\n", of);
239     cursorto(of, 40, 7 + fprintf(of, "\t%i,",
240             (int)(afm->WinMetrics.sAscender)));
241     fputs("/* WinMetrics.sAscender */\n", of);
242     cursorto(of, 40, 7 + fprintf(of, "\t%i,",
243             (int)(afm->WinMetrics.sDescender)));
244     fputs("/* WinMetrics.sDescender */\n", of);
245     cursorto(of, 40, 7 + fprintf(of, "\t%i,",
246             (int)(afm->WinMetrics.sLineGap)));
247     fputs("/* WinMetrics.sLineGap */\n", of);
248     cursorto(of, 40, 7 + fprintf(of, "\t%i,",
249             (int)(afm->WinMetrics.sAvgCharWidth)));
250     fputs("/* WinMetrics.sAvgCharWidth */\n", of);
251     cursorto(of, 40, 7 + fprintf(of, "\t%i,",
252             (int)(afm->WinMetrics.sTypoAscender)));
253     fputs("/* WinMetrics.sTypoAscender */\n", of);
254     cursorto(of, 40, 7 + fprintf(of, "\t%i,",
255             (int)(afm->WinMetrics.sTypoDescender)));
256     fputs("/* WinMetrics.sTypoDescender */\n", of);
257     cursorto(of, 40, 7 + fprintf(of, "\t%i,",
258             (int)(afm->WinMetrics.sTypoLineGap)));
259     fputs("/* WinMetrics.sTypoLineGap */\n", of);
260     cursorto(of, 40, 7 + fprintf(of, "\t%u,",
261             (unsigned int)(afm->WinMetrics.usWinAscent)));
262     fputs("/* WinMetrics.usWinAscent */\n", of);
263     cursorto(of, 40, 7 + fprintf(of, "\t%u",
264             (unsigned int)(afm->WinMetrics.usWinDescent)));
265     fputs("/* WinMetrics.usWinDescent */\n",of);
266     fputs("    },\n    {\n", of);
267     writeCharWidths(of, afm);
268     cursorto(of, 48, fprintf(of, "    %i,", afm->NumofMetrics));
269     fputs("/* NumofMetrics */\n", of);
270     cursorto(of, 48, fprintf(of, "    met_%s,", buffer));
271     fputs("/* Metrics */\n", of);
272     if (afm->Encoding == &PSDRV_AdobeGlyphList)
273         cursorto(of, 48, fprintf(of, "    &PSDRV_AdobeGlyphList"));
274     else
275         cursorto(of, 48, fprintf(of, "    &enc_%s", buffer));
276     fputs("/* Encoding */\n};\n", of);
277 }
278
279 void PSDRV_AFM2C(AFM *afm)
280 {
281     char    buffer[256];
282     FILE    *of;
283     int     i;
284     
285     strncpy(buffer, afm->FontName, sizeof(buffer) - 3);
286     buffer[sizeof(buffer) - 3] = '\0';
287     
288     for (i = 0; i < strlen(buffer); ++i)
289         if (buffer[i] == '-')
290             buffer[i] = '_';
291             
292     buffer[i] = '.';  buffer[i + 1] = 'c';  buffer[i + 2] = '\0';
293
294     MESSAGE("writing '%s'\n", buffer);
295     
296     of = fopen(buffer, "w");
297     if (of == NULL)
298     {
299         ERR("error opening '%s' for writing\n", buffer);
300         return;
301     }
302     
303     buffer[i] = '\0';
304     
305     writeHeader(of, afm, buffer);
306     
307     if (afm->Encoding != &PSDRV_AdobeGlyphList)
308         writeEncoding(of, afm, buffer);
309         
310     writeMetrics(of, afm, buffer);
311     writeAFM(of, afm, buffer);
312     
313     fclose(of);
314 }